1
\$\begingroup\$

I want to apply multi-thread in a simple way to control and draw 4000 objects. I am using SDL and OpenGL.

control : locations, collisions, calculations ... etc

draw : OpenGL draw functions glDrawArrays,glDrawElements etc

For 4000 objects i think like this: enter image description here

do you think it works ?

\$\endgroup\$
  • \$\begingroup\$ Your question is not clear. Why are you putting so much effort? What's the desired result? If your game lags because you are drawing too many complicated objects, creating more threads will not solve the issue. \$\endgroup\$ – TomTsagk Dec 7 '18 at 13:10
  • \$\begingroup\$ Also, you probably don't have multiple GPUs, so multiple threads won't help much \$\endgroup\$ – Bálint Dec 7 '18 at 13:25
  • \$\begingroup\$ I just wondered. Then can i just apply to controls for cpu operations like this way ? \$\endgroup\$ – Emre Kaya Dec 7 '18 at 13:30
  • \$\begingroup\$ @EmreKaya: "I want to apply multi-thread in a simple way to control and draw 4000 objects." Nothing about multi-threaded rendering, particularly in OpenGL, is going to be simple. And you should never have an infinite loop that creates threads like this. Threads are heavyweight, OS objects, not light-weight tasks. \$\endgroup\$ – Nicol Bolas Dec 7 '18 at 16:12
3
\$\begingroup\$

It is definitely possible and useful to make your rendering multithreaded, but it wouldn't work the way you've proposed. Keep in mind that with OpenGL, you're drawing all the objects for a frame into the same context. If you have 2 threads changing state in the same context at the same time, things are going to get very confused. So you have to be very careful with your threads.

Another way to architect this would be to have 3 threads and 3 contexts in the same share group. It would work something like this:

thread | t = 1             | t = 2             | t = 3             | t = 4            |
1      | calc pos. @ t = 1 | draw @ t = 1      | calc pos. @ t = 3 | draw @ t = 3     |
2      | idle              | calc pos. @ t = 2 | draw @ t = 2      | calc pos @ t =  4|
3      | idle              | idle              | disp. frame 1     | disp. frame 2    |

And so on. So thread 1 calculates all objects positions at time t = 1. Threads 2 and 3 are initially idle.

At time t = 2, thread 1 draws all 4,000 objects into a texture-backed FBO in context A. Meanwhile, thread 2 starts calculating the objects positions at time t = 2. Thread 3 is still idle.

At time t = 3, thread one starts calculating the positions of the objects at time t = 3. Thread two meanwhile is drawing the objects at their positions from t = 2 into a different texture-backed FBO in context B. Now thread 3 kicks in and simply blits the frame 1 texture to the screen.

As you probably figured, at time t = 4, thread 1 draws the objects from their positions at t = 3. Thread 2 calculates the objects positions for t = 4. Thread 3 blits the frame 2 texture to screen.

This way, any given context is only drawn to on a single thread. Threads alternate whether they are calculating object positions or drawing objects. One thread is dedicated to just drawing the frames to the screen.

Note that you will need some sort of synchronization primitive to ensure that things happen in order and not before parts are ready. Something like a semaphore would probably work well. So thread 2 would wait on a semaphore before starting to calculate frame 2's positions. When thread 1 finished calculating frame 1's objects' positions, it would signal the semaphore so thread 2 could start the calculations for frame 2. You could do the same thing for drawing and blitting.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.