I want to load assets for my OpenGL application in a separate thread so that I can create a loading screen, but when I try to call an OpenGL function in another thread, the application crashes, and I need them to load textures. Is there anyway I can use multithreading and OpenGL? Or am I going to say, load an asset every frame, and make the screen kinda choppy and bad looking? I've seen that you can accomplish this on Windows, but I want this to run on Unix (specifically MacOSX) much more than windows.
Messing with a single OpenGL context in different threads is usually bound to result in trouble. What you can do though is make use of a Pixel Buffer Object (PBO) for the texture update, map this in the main (OpenGL) thread, pass the mapped pointer to the loading thread to be filled with file contents, and unmap the PBO followed by a glTexImage2D (using the PBO, of course) in the main thread once the loading thread has finished. By using two different PBOs, one that is currently filled by the loading thread and one that is currently copied into a texture by the main thread and some proper synchronization, you can get the file loading and texture update to work concurrently (look at the linked tutorial for some, yet single-threaded, examples).
Related
I have several QQuickFramebufferObjects between which I want to share some GL objects (shaders and VBOs mainly). My initial plan was:
Create a class SharedGLData to hold the shared object
Instantiate this class on the stack in C++'s main()
Pass a pointer the object to QML via ctx->assignRootProperty or something
Pass the object as a property to the QML items of type SharedGLData
Access the pointer from C++
But that means I'd be creating GL objects on the main thread and later access them on the render thread. I'm pretty sure that's forbidden, for example see here where it says:
QOpenGLContext can be moved to a different thread with moveToThread(). Do not call makeCurrent() from a different thread than the one to which the QOpenGLContext object belongs.
Is it ok to follow my initial plan or is there a way to create shared GL objects on the render thread?
A possible hack would be to put the shared stuff into a singleton that gets initialized on first use, and make my first use be directly from the rendering code. But that's a hack.
Another idea is to call moveToThread on the QQFBO's GL context to move it to the main thread, instantiate SharedGLData, then move the GL context back to the render thread. But I don't have a pointer to the render thread...
Clarification after the answer I got: By "render thread" I mean the thread that Qt SceneGraph silently creates to do all the rendering. It's not a thread that I'm creating!
If you want multiple threads sharing OpenGL objects,
Create a QOpenGLContext. Usually, the first one you create should be the one belonging to the window (which will actually draw to the screen).
Create a second QOpenGLContext, but call setShareContext before calling create.
You now have two OpenGL contexts which share objects (shaders, VBOs, etc) and you can now use these contexts simultaneously from different threads.
But... this often not an ideal experience. In many cases, using OpenGL simultaneously from different threads will be no faster than using it from one thread, or it will be slower, or it will be buggier. You are at the mercy of the OpenGL implementation.
A Different Way
It sounds like your goal is to load assets (shaders, textures, vertex data) in a background thread while your main thread continues to render. There is a more straightforward way of doing this that does not involve creating multiple contexts at all.
Simply map OpenGL buffers into memory in the rendering thread, and then pass the pointer to the background loader thread. The loader thread is free to write data into the buffer while the render thread continues to make OpenGL calls. When the loader thread is done, it signals the main thread, which does the appropriate synchronization and calls glTexImage2D or whatever. These days, you can even keep a single buffer persistently mapped, but the traditional two-buffer method also works quite well.
Under this scheme, your rendering thread does not have to do any IO, and your background thread does not have to make any OpenGL calls at all.
You can't use this to compile shaders in the background but c'est la vie.
Listed below are some API issues I expect to encounter when adding a render thread to code so that all graphics API calls that used to all occur on the main thread now occur on a dedicated background thread.
For Direct3D and OpenGL on Win32, are there additional issues that are involved that I'm not aware of, or has my list covered it?
List of expected issues:
D3D9: http://msdn.microsoft.com/en-us/library/windows/desktop/bb147224%28v=vs.85%29.aspx . This basically means allowance has to be made for particular special operations to occur on the main thread with D3D9.
D3D10+: http://msdn.microsoft.com/en-us/library/windows/desktop/ee417025.aspx#Multithreading_and_DXGI . This basically means that the main thread (with the message pump) shouldn't block waiting on the render thread (specifically, for the render thread to make DXGI calls).
OpenGL: no issues so long as the context is only active on the render thread, but as above some care during mode changes, etc.
Note: assume my application has been careful to store and isolate all of the data the render thread will require to complete its processing, such as input buffer data, etc. I am asking specifically about window system and API-level issues and any gotchas.
I have a Delphi 6 application that receives and processes an image stream from an external camera. I have the code on a background thread since it is CPU heavy and I don't want it interfering with with the user interface code that runs on the main thread. I want to update a rectangular area on a form or frame with the TBitmaps I create from the camera's JPEG frames that are received at a rate of 25 frames per second.
I want to know what method will give me the best performance and what Windows API calls or Delphi calls to use to do it. I would guess I should not use a TImage or TPicture or similar VCL component because they run on the main thread and I'm pretty sure trying to get anything done via a Synchronize() call is going to be inefficient and has the potential to slow down the threads involved. I would also want a technique that provides a smooth video display like double buffered controls do without any "striping" effects. Also, any tips on proper Canvas locking or device context management, etc. would be appreciated, especially tips on avoiding common mistakes in freeing resources.
Of course, a link to a good code sample that does what I need would be great.
AFAIK TBitmap are thread-safe, if you work only on its canvas. Synchronize is needed if you send GDI messages and need to refresh the screen, but from my experiment, using TBitmap.Canvas is just a wrapper around thread-safe Windows API. If you process the bitmap with pixel arithmetics (using e.g. Scanline), one unique bitmap per thread, you can do it on background.
But I suspect using TBitmap is not the most efficient way. Give a try to http://graphics32.org or http://aggpas.org which are very fast way to work on bitmaps.
If you can, as imajoosy proposed, the best way to process your input stream is to use direct X streaming process abilities.
For thread-safe process, if each thread is about to consume 100% of its core (which is very likely for image process), it is generally assumed that you shall better create NumberOfCPU-1 threads for your processing. For instance, you could create a pool of threads, then let those consume the bitmaps from the input stream.
suppose I use the QGLWidget's paintGL() method to draw into the widget using OpenGL. After the Qt called the paintGL() method, it automatically triggers a buffer swap. In OpenGL, this buffer swap usually blocks the calling thread until the frame rendering to the background buffer is completed, right? I wonder which Qt thread calls the paintGL as well as the buffer swap. Is it the main Qt UI thread? If it is, wouldn't that mean that the block during the buffer swap also blocks the whole UI? I could not find any information about this process in general..
Thanks
I don't use the QGLWidget very often, but consider that yes, if swapBuffers() is synchronous the Qt GUI thread is stuck. This means that during that operation you'll be unable to process events.
Anyway, if you're experiencing difficulties while doing this, consider reading this article which manage to allow multithreaded OpenGL to overcome this difficulty.
Even better, this article explains well the situation and introduces the new multithreading OpenGL capabilities in Qt 4.8, which is now in release candidate.
In OpenGL, this buffer swap usually blocks the calling thread until the frame rendering to the background buffer is completed, right?
It depends on how it is implemented. Which means that it varies from hardware to hardware and driver to driver.
If it is, wouldn't that mean that the block during the buffer swap also blocks the whole UI?
Even if it does block, it will only do so for 1/60th of a second. Maybe 1/30th if your game is slowing down. If you're really slow, 1/15th. The at most one keypress or mouse action that the user gives will still be in the message queue.
The issue with blocking isn't about the UI. It will be responsive enough for the user to not notice. But if you have strict timings (such as you might for a game), I would suggest avoiding paintGL at all. You should be rendering when you want to, not when Qt tells you to.
I am trying to come up with a synchronization model for the following scenario:
I have a GUI thread that is responsible for CPU intensive animation + blocking I/O. The GUI thread retrieves images from the network (puts them in a shared buffer) , these images are processed (CPU intensive operation..done by a worker thread) and then these images are animated ( again CPU intensive..done by the GUI thread).
The processing of images is done by a worker thread..it retrieves images from the shared buffer processes them and puts them in an output buffer.
There is only once CPU and the GUI thread should not get scheduled out while it is animating the images (the animation has to be really smooth). This means that the work thread should get the CPU only when the GUI thread is waiting for I/O operation to complete.
How do i go about achieving this? This looks like a classic producer consumer problem...but i am not quite sure how i can guarantee that the animation will be as smooth as possible ( i am open to using more threads).
I would like to use QThreads (Qt framework) for platform independence but i can consider pthreads for more control ( as currently we are only aiming for linux).
Any ideas?
EDIT:
i guess the problems boils down to one thing..how do i ensure that the animation thread is not interrupted while it is animating the images ( the animation runs when the user goes from one page to the other..all the images in the new page are animated before shown in their proper place..this is a small operation but it must be really smooth).The worker thread can only run when the animation is over..
Just thinking out loud here, but it sounds like you have two compute-intensive tasks, animation and processing, and you want animation to always have priority over processing. If that is correct then maybe instead of having these tasks in separate threads you could have a single thread that handles both animation and processing.
For instance, the thread could have two task-queues, one for animation jobs and one for processing jobs, and it only starts a job from the processing queue when the animation queue is empty. But, this will only work well if each individual processing job is relatively small and/or interruptible at arbitrary positions (otherwise animation jobs will get delayed, which is not what you want).
The first big question is: Do I really need threads? Qt 's event system and network objects make it easy to not having the technical burden of threads and all the snags that comes with it.
Have a look at alternative ways to address issues here and here. These techniques great if you are sticking to pure Qt code and do not depend on a 3rd party library. If you must use a 3rd party lib that does blocking calls then sure, you can use threads.
Here is an example of a consumer producer.
Also have a look at Advanced Qt Programming: Creating Great Software with C++ and Qt 4
My advice is to start without threads and see how it fares. You can always refactor to threads after. So, best is to design your objects/architecture without too much coupling.
If you want you can post some code to give more context.