|
Object
The object component, also called a system object, is an object within
the scene and is typically associated with what is visible to the user
on-screen.
The universal object uses the system object as an extension of its
functionality, described in "Universal Scene and Objects", to allow the
properties this object provides to be exposed via the universal object.
For example, a universal object could extend geometry, graphics, and
physics to create a beam of wood on-screen. The geometry system
would hold the position, orientation, and scale information of the
object. The graphics system would display the beam on-screen
using the given mesh, and the physics system would apply rigid body
collision to the beam so that it would correctly interact with other
objects and with gravity.
In certain situations a system object may be interested in the
changes of a different universal object, or one of the universal object's
extensions. In this case a link can be established so that the
system object can observe the other object.
Task
The task component, referred to as a system task, operates on the
scene. When the task receives a command to update from the task
manager, the task performs the system's functionality on the objects
within the scene.
The task can also choose to subdivide its execution into subtasks
and schedule the subtasks with the task manager for even more
threaded execution. Doing this allows the engine to scale more readily
to a configuration with multiple processors. This technique is known
as data decomposition.
During the task's update of the scene, any modifications done to its
objects are posted to the state manager.
Tying It All Together
The engine execution can be broken up into several stages:
initialization, scene loading, and game loop.
Initialization
Engine execution begins by initializing the managers and
the framework.
1. The framework calls the scene loader to load in the scene.
2. The loader determines what systems the scene is using, and
then calls the platform manager to load those modules.
3. The platform manager loads the modules, passes in the manager
interfaces, and then calls into them to create a new system.
4. The system module returns a pointer to the instantiated system
that implements the system interface.
5. The system module registers any services it provides with the
service manager.
Figure 10. The engine manager and system initializations.
Scene-Loading
Control returns to the loader, which loads the scene.
1. The loader creates a universal scene and calls each system
interface to instantiate system scenes, extending the
functionality of the universal scene.
2. The universal scene checks each system scene for any shared
data changes they could make and for shared data changes they
want to receive.
3. The universal scene then registers the matching system scenes
with the state manager so they will be notified of the changes.
4. 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 occurs for the
universal scene.
5. The loader instantiates system objects via the system scene
interfaces it previously received and extends the universal
objects with the system objects.
6. 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. The universal scene and object initializations.
Game Loop
The main game loop begins processing.
1. The platform manager is called to process all window messages
and other platform-specific items that are needed for operation
on the current platform.
2. Execution is then transferred to the scheduler, which waits for
the clock time to expire before proceeding.
3. The scheduler, for free step mode, checks which of the system
tasks completed execution in the previous clock. All tasks that
have finished (that is, they are ready to execute) get issued to
the task manager.
4. The scheduler now determines which tasks will complete on
the current clock and waits for completion of those tasks.
5. For lock step mode, the scheduler issues all tasks and waits
for them to complete for each clock step.
Task Execution
Execution is transferred to the task manager.
1. The task manager queues all submitted tasks and starts
processing each one 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).
2. As tasks execute they operate on the entire scene or on specific
objects and modify their internal data structures.
3. Any data that is considered shared, such as position and
orientation, need to be propagated to the other systems. To do
this, the system task has 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.
4. The change controller queues the change information to be
processed later, but change types that the observer is not
interested in are simply ignored.
5. 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 (that is, the
user input system changes the screen resolution of the
graphics system).
6. Tasks can also call into the environment manager to read
environment variables, and change the runtime state (pause
execution, go to next scene, and so on).
Figure 12. The task manager and tasks.
Distribution
Once all tasks targeted for the current clock have completed execution,
the main loop calls the state manager to distribute the changes.
1. The state manager calls each of its change controllers to
distribute the changes they have queued. This is done by going
through each subject's changes and seeing which observer was
listening to that subject.
2. 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.
3. The observers that are interested in the changes done by a
system object will typically be other system objects that are
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, any universal
objects' extensions that are linked should be grouped together
in a task.
Runtime Check and Exit
The final step of the main loop is to check the runtime's state, which
might be run, pause, or next scene. If the runtime state is set to run,
it will repeat the entire game loop. If the runtime is set to exit, it exits
the game loop, frees up resources, and exits the application.
|
Reminds me of Erlang.
Can you post some test results ?
Corei7 performance scaling will probably be decent (around 4x I bet) :p
But did you have the opportunity to tests on a xeon 7400 (6 cores) or on a dualxeon (12 cores) ?
Vincent