Using correct threading in the game

I am currently developing a 3D game that is supposed to simulate deformable 3D objects. With deformable, I mean that the geometry of a 3D object changes from frame to frame. The game has a render loop that needs to run as often as possible (at least 30 times / sec) to get the frame rate of the trigger. But in this render loop I do two more things: calculating new geometry and calculating bounding box hierarchy (AABVH). I need AABVH for collision detection. It is very important that the geometry and AABVH calculations are completed before the 3D object is rendered. Computing new geometry and AABVH is a tedious task, so the frame rate drops quickly. So my idea was to compute AABVH in a separate thread. It looks like this:

Thread t;
public void Render(Object3D o) // renders 3D object
{
  if (t != null) // wait until the new geometry got calculated
  {
     t.Join();
  }
  o.RenderGeometry();
  t = new Thread(() => o.CalcAABVH());
  t.Start();
}

      

I am not an experiment in parallel programming in C #, but I am pretty sure this is not a good solution. Each frame, a new thread is created, executed and destroyed, which causes a lot of overhead. What would a good solution look like in my case?

+3


source to share


2 answers


You shouldn't block rendering of the next frame when updating geometry. You can also do the calculation synchronously. Blocking render will increase the overall render time for each frame and have a negative impact on the frame rate - an effect you specifically avoid!

Instead, use a flag to indicate whether a new geometry is computed, and if so, render the old geometry. Now you need 2 sets of geometry - as with the framebuffer, you change them when the new geometry is complete.

The net effect will be that some frames may not have the latest geometry available when you want it. This will be more noticeable for objects where the geometry takes longer to compute. Most graphics programs for games are smoke and mirrors, so don't worry about that.

Implementation



Please use a threadpool for these update operations as the creation cost is cheaper. Ideally use a parallel task library. As a bonus, the facility Task

tracks its current status for you!

    using System.Threading.Tasks;

    ...

    Task t;
    public void Render(Object3D o) // renders 3D object
    {
        if(t != null && t.Status == System.Threading.Tasks.TaskStatus.Running)
        {
            //render old geometry
        }
        else
        {
            t = Task.Factory.StartNew(o.CalcNewGeometry())
                    .ContinueWith(p => o.UpdateGeometry); //swap the new geometry in
        }
    }

      

You will need sync here to make sure you don't change your new geometry while rendering the old geometry. I'll leave it up to you.

+3


source


Multithreading in games is mainly (depending on genre, functions, ...) used as follows:

  • 1 Thread - Rendering

  • 1..x Themes - Physics (where your deformations will belong)

  • x Themes - AI


Display the actual state of an object, deform it into a copy in a physical stream. Switch objects after deforming as suggested by Gusdor.

I would suggest using something like the ConcurrentQueue class to queue up objects to be computed by the physical thread. This way you don't need to recreate the streams every time. Just let them sit idle and calculate the moment something enters the queue.

+2


source







All Articles