I am attempting to write a multi threaded "load from disk" algorithm for my C++/OpenGL game engine.
My current situation is as follows:
Thread #0(main thread): Core engine functions, Rendering work.
Thread #1: Spatial processing //Physics, etc. Not really relevant to the problem.
Thread #2: background loading from disk
The algorithm loads Entity details from an XML file on disk, which contains graphics information, such as model and texture files for rendering.
The idea is that the engine should be capable of loading entities from disk, and then from memory to the GPU without blocking the main thread. However, at the moment, it can only load into main memory.
Whenever I load data on thread 2, I have to notify thread 0 that the load from disk is complete. Then the engine code running on thread 0 makes the necessary GL calls to send data from memory to the GPU, and sends the entities to the renderer.
I am aware that making OpenGL calls on multiple threads is undefined and will cause the program to crash.
I am also aware that it is possible to have a shared gl context, and that on each thread that you want to make GL calls, you must first make the context current (Synchronise), then make the calls.
As I understand it, making a GL context current will make all other contexts on other threads inactive, which leads us back to the undefined behaviour/crash situation.
I would prefer that the VAO/VBO/texture object populating is done on thread 2. I think this could be achieved by creating a context on thread 2, and making it currently active context, but I am unsure how this would affect rendering. Would I have to stop rendering whilst this is being done? If so, then I don't see any benefit as it may as well be done on the main thread.
Is there a way to create and populate buffer objects on thread 2, whilst not interfering with rendering operations on thread 0?
To Clarify:
- Thread 2 will never perform rendering, only loading of data onto the GPU.
- Thread 0 only works with already populated buffers. It will only be given data that already exists on the GPU.
-
Have you looked into Shared OpenGL contexts? You basically have two contexts which use the same data objects then. This allows you to issue the calls needed for data loading from another thread without moving the context. Maybe checkout stackoverflow.com/questions/55885139/…BDL– BDL2020年05月07日 12:03:21 +00:00Commented May 7, 2020 at 12:03
-
Looking at shared contexts, It looks like buffer objects can be created, but VAO's cannot, which is an issue. Also, you still need to make the context current. Would this not interfere with rendering?Ian Young– Ian Young2020年05月07日 13:16:14 +00:00Commented May 7, 2020 at 13:16
-
VAO: VAO creation is cheap/fast and can be done in the render thread. Make context current: You have two context, one for each thread. You only have to make them current on startup. Interfer with rendering: The graphics card is a limited resource. So yes, when you have two threads doing heavy operations in there context this will slow down rendering. But that would also be the case if you do it in one context and switch threads or when doing it in one thread.BDL– BDL2020年05月07日 13:35:24 +00:00Commented May 7, 2020 at 13:35