One question keeps bothering me and I seek your wisdom.
Wall of text incoming, forgive me.
The question is about multithread drawing.
Just to note that I’ve read a lot of materials here in the forums and stackoverflow and this is not one of those
“I’m trying to do multithread rendering in my game for better speed 101”.
I have an linux ubuntu based application (a game basically), which also needs to communicate constantly
with several other hardware devices.
For more than a year I’ve kept everything on the main thread
(communications with hardware devices + event polling + update game state + rendering) while maintaining concrete 60 FPS.
Until now I uploaded all the textures to the GPU at program startup.
The problem came when I needed to use several really big textures (8192x8192px).
I had to implement dynamically texture loading/unloading. So I did and it worked.
Now the problem is when I need to upload one of those huge textures to the GPU (8192x8192px) with SDL_CreateTextureFromSurface() the program hangs for huge amount of time ~1000ms (no wonder with such huge texture).
When the call to SDL_CreateTextureFromSurface() returns control - the hardware communications that I need to support timed out long time ago.
So after so much time I finally decided to try and move the rendering to a secondary thread.
I think it worked (it is now completely finished but still…).
Main thread creates the window, spawns a rendering thread and sleeps for some time.
The secondary(renderer thread) creates the SDL_Renderer and sleeps on a condition_variable.
Main thread awakes and continues execution.
Main thread is responsible for event polling, updating the game state and maintaining the communication with the hardware devices.
No rendering related operation are ever made from main thread (it only stores draw “commands” in a commandQueue and drawDataBuffer).
2 copies of the commandQueue and drawDataBuffer are used so no almost zero-locking is achieved.
After all draw “commands” are stored the main thread locks on a mutex, switches the commandQueue pointers and wakes the second(rendering) thread that was sleeping on a condition_variable.
Rendering thread wakes, walks the commandQueue and performs rendering related code after which sleep again.
The process repeats for every frame.
SDL/OpenGL requires all rendering calls to come exactly from 1 thread.
The thread that created the SDL_Renderer(as far as I know?)
(or the thread that owns the current OpenGL context if you are directly using OpenGL).
If you are still reading this here comes my real question:
How come I can make successful calls from my main thread to SDL_CreateTextureFromSurface(), while it is the other thread that is related to rendering operations(the one that created the SDL_Renderer)?
Does the application suffer a penalty for “context switching” of some kind when I make calls from main thread?
Is there a problem with me having the drawing thread as a second thread, while I keep the main thread to update the game state?
Is there some kind of penalty for not performing drawing in the main thread (in my case from the secondary rendering thread)?
Do you think I should “swap” their places -> draw in the main thread and make the secondary thread updating the game state and if yes - why?