Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Designing the Framework of a Parallel Game Engine


6. Tying It All Together

This is a lot of information to absorb all at once, and the different sections aren't really separate from one another. The entire engine execution can be broken up into several stages as described in the following sections.

6.1. Initialization Stage

Engine execution begins by initializing the managers and the framework.

  • The framework calls the scene loader to load in the scene.
  • The loader determines what systems the scene is using then calls the platform manager to load those modules.
  • The platform manager loads the modules, passes in the manager interfaces, then calls into them to create a new system.
  • The module returns a pointer to the instantiated system which implements the system interface.
  • The system module will also register any services it provides with the service manager.

Figure 10: Engine Manager and System Initialization

6.2. Scene Loading Stage

Control returns to the loader which loads the scene.

  • The loader creates a universal scene and calls each system interface to instantiate system scenes, extending the functionality of the universal scene.
  • The universal scene checks each system scene for what shared data changes they could possibly make and what shared data changes they would like to receive.
  • The universal scene then registers the matching system scenes with the state manager so that they will be notified of the changes.
  • The loader creates a universal object for each object in the scene and determines which systems will be extending the universal object. The universal object follows a similar system object registration pattern with the state manager as that of the universal scene.
  • The loader instantiates system objects via the system scene interfaces it previously received and extends the universal objects with the system objects.
  • The scheduler then queries the system scene interfaces for their primary tasks because the scheduler is responsible for issuing the primary tasks to the task manager during execution.

Figure 11: Universal Scene and Object Initialization

6.3. Game Loop Stage

  • The platform manager is called to process all window messages and/or other platform specific items that are needed for operation on the current platform.
  • Execution is then transferred to the scheduler, which waits for the clock time to expire before proceeding.
  • The scheduler, for free step mode, checks which of the system tasks completed execution in the previous clock. All tasks that are done (i.e. ready to execute) get issued to the task manager.
  • The scheduler will now determine which tasks will complete on the current clock and waits for completion of those tasks.
  • For lock step mode, the scheduler issues all tasks and waits for them to complete for each clock step.

6.3.1. Task Execution

Execution is transferred to the task manager.

  • The task manager queues up all tasks submitted to it and starts processing each task as threads become available. (Task processing is specific to each system. Systems can operate using only one task or they can issue more tasks which get queued in the task manager, thus potentially getting executed in parallel).
  • As tasks execute they will operate on the entire scene or on specific objects and modify their internal data structures.
  • Any data that is considered as shared, like position and orientation, needs to get propagated to the other systems. The system task does this by having the system scene or system object (whichever was changed) inform their observer of the change. In this case the observer is actually the change controller located in the state manager.
  • The change controller queues up the change information to be processed later, but change types that the observer is not interested in are simply ignored.
  • If the task needs any services it goes through the service manager to call into the provided service. The service manager can also be used to change the property of a different system that isn't exposed via the messaging mechanism (e.g. the user input system changes the screen resolution of the graphics system).
  • Tasks can also call into the environment manager to read environment variables, change the runtime state (e.g. pause execution, go to next scene, etc.).

    Figure 12: Task Manager and Tasks

    6.3.2. Distribution

    Once all tasks targeted for the current clock have completed execution, the main loop calls the state manager to distribute the changes.

    • The state manager calls each of its change controllers to distribute the changes they have queued up. This is done by going through each subject's changes and seeing which observer was listening to that subject.
    • The change controller then calls the observer informing it of the change (a pointer to the subject's interface is also passed to the observer). For free step mode, the observer gets the changed data from the change controller, but for lock step mode the observer queries the subject for the data.
    • The observers that are interested in the changes done by a system object will typically be other system objects that are all attached to the same universal object. This makes it possible for the change distribution to be broken up into tasks for execution in parallel. To limit synchronization, group together in a task any universal objects' extensions that are linked.

    6.3.3. Runtime Check and Exit

    The final step of the main loop is to check the runtime's state. There are several runtime states like: run, pause, next scene, etc. If the runtime state is set to run it will repeat the entire game loop. If the runtime is set to exit then it exits the game loop, frees up resources, and exits the application. Other runtime states can be implemented like pause, go to next scene, etc.

    Final Thoughts

    The key takeaway from all of this is section 2, "Parallel Execution State". Designing systems for functional decomposition, coupled with data decomposition will deliver a good amount of parallelization and will also ensure scalability with future processors with an even larger amount of cores. Remember to use the state manager along with the messaging mechanism to keep all data in sync with only minimal synchronization overhead.

    The observer design pattern is a function of the messaging mechanism and some time should be spent learning it so that the most efficient design possible can be implemented to address the needs of your engine. After all, it is the mechanism of communication between the different systems to synchronize all shared data.

    Tasking plays an important role in proper load balancing. Following the tips in Appendix D will help you create an efficient task manager for your engine.

    As you can see, designing a highly parallel engine is manageable by using clearly defined messaging and structure. Properly building parallelism into your game engine will give it significant performance gains on modern and all future processors.


    Jeff Andrews is an Application Engineer with Intel working on optimizing code for software developers, currently focused on PC gaming. He also researches different technologies for enhancing performance or for adding new features to games, which included a role of lead architect for Intel's Smoke demo framework.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.