Multithreaded Renderloop - 3

Download Alpha and Omega v2.7.1.13.0
Binaries as Win32 Installer (3 MB)
Download Alpha and Omega v2.7.1.13.0
Source as Visual Studio 2010 Solution (28 MB)

Today it'll be just a small update. I'm busy writing Part 3 (henceforth called part 4), but I thought it would be fun to show you guys some cool stuff. I've also cleaned up some code and removed some minor bugs.

To test if determinism worked (on a single computer) we've created a test using the Farseer Physics Engine. I will not use Farseer for the actual game that I have in mind because it'll be 3D. Maybe I'm gonna use Farseer for testing determinism on networking code since it's pretty easy to work with. See the video below to see our test in action:

  

For part 4 expect a whole lot more text :)

 

  1. Kurt says:

    I like how you explained decoupling the logic and render operations into different threads. This is something I want to do for my own engine (a Java course project I did last year).

    I have one question, seeing as I am no where near a guru, and that is how would we implement these 3 different render states?

    I am seeing making copies of game objects or storing this information in 3 collections within each active object.

    Does that make sense? It seems like having these shifting render states could potentially use a lot of memory?

    Thoughts? Suggestions?

    • eierkoek eierkoek says:

      First of all, the methods used (triple buffering) are based on the requirements described at the start of part 1. In most cases it would be a lot easier to implement a different multithreaded method than the ones describes in these posts. Given the difficulty involved, it may be better to look at other methods. Triple buffering is a method common to multithreaded programming, even Wikipedia has a paragraph on it:
      http://en.wikipedia.org/wiki/Multiple_buffering#Triple_buffering
      (not to be confused with triple buffering on the video card)

      If you are still sure you'd like to use triple buffering:

      Implementation of the triple buffer start by splitting game objects into:
      - Required video card resources (textured, models, shaders, ...)
      - All additional rendering information (position, transformation matrices, ...)
      - Everything else only used by the update thread (Momentum-vectors, AI, ...)

      Only the render-information is stored in a triple-buffer and that usually has a very low memory requirement (a couple of vectors and matrices). Even though the expected memory usage will not be 'that' high, it will be a little bit higher compared to traditional rendering loops.

      After splitting it, the difficult part is to get them synchronized. In part 2, at "Separation of Render State(s) and Rest State" we've shown that even though the update-thread is able to delete some node, it may not delete all 3 corresponding render-nodes (because the render thread may be busy rendering one right now). We don't want to use mutexes, so all that's left was using a message-system.

      Java (and C#) will handle memory management by running the garbage collector once in a while. This hides some of the additional caveats. You don't want to 'new' or copy an object every frame because that will allocate memory on the heap which will likely be freed sometime in the future by the garbage collector. So no cloning of render-state nodes each and every frame because all that memory shuffling will slow down the update-thread.

      Instead of:
      Player.Position += movement;

      It'll be:
      RenderState.Player.Position = PreviousRenderState.Player.Position + movement;

      Another (simpler) way of applying multithreading (that does not require triple buffering) is to let the update thread(s) run one frame ahead of the drawing thread. The update thread(s) will create 'update-messages' (such as "Move Object X to Position Y") that will will be applied the moment that the render thread is done rendering. This method is way easier to implement and for most scenario's it'll be good enough.

      Good luck with your game-engine! Building an engine is really fun and gives plenty of enjoyable challenges. Just seeing your hard work come to life in fun demos and games makes it all that more awesome!

      • Kurt says:

        Hey man, thanks for the quick and detailed response. I am still very interested in doing it 'this' way as opposed to just what I need to accomplish goal 1. I'm more looking at what I might need to accomplish goal 5+.

        You have given me some terminology to look into that I am sure will bring me closer to understanding how to do this.

        And, I agree. Building this engine, plus the game, in 6 weeks was a massive challenge (glad my wife supports my education as she didn't see me for about 4 of those weeks). However, I learned more doing it then most of my other programming courses combined.

      • eierkoek eierkoek says:

        I just realized that the Wikipedia link I added was about triple buffering on the video card :P. (I don't want that... that costs precious memory on the video card)

        Normal triple buffering for multithreading is explained here

line