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\$
4
  • \$\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\$ Commented Dec 7, 2018 at 13:10
  • \$\begingroup\$ Also, you probably don't have multiple GPUs, so multiple threads won't help much \$\endgroup\$
    – Bálint
    Commented Dec 7, 2018 at 13:25
  • \$\begingroup\$ I just wondered. Then can i just apply to controls for cpu operations like this way ? \$\endgroup\$
    – Emre Kaya
    Commented Dec 7, 2018 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\$ Commented Dec 7, 2018 at 16:12

2 Answers 2

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\$
0
\$\begingroup\$

The most important feature is response time to user interaction. The render engine must scale well with increasing number of visible objects. The best way to solve this issue is to use progressive rendering instead of multi-threaded rendering. Progressive rendering renders all objects across several consequent frames instead of trying to complete everything in just one frame. Each next frame increases the amount of detail in distance from the viewer. There is only one OpenGL render thread with this approach. This OpenGL thread can be the same as the main GUI thread.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .