geek poke A Dynamic Component Architecture for High

  • Slides: 76
Download presentation

geek & poke

geek & poke

A Dynamic Component Architecture for High Performance Gameplay Terrance Cohen Lead Systems Engineer Insomniac

A Dynamic Component Architecture for High Performance Gameplay Terrance Cohen Lead Systems Engineer Insomniac Games

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example • Questions (note slide #)

A Dynamic Component Architecture for High Performance Gameplay • Purpose o Statement of Problem

A Dynamic Component Architecture for High Performance Gameplay • Purpose o Statement of Problem o Proposed Solution • The Dynamic Component System • Implementation by Example

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy o Memory:

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy o Memory: binds data @ compile time § Allocated throughout lifetime

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory:

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory: binds data @ compile time o Performance: poor cache coherence § Arrays of non-homogeneous objects § Virtual dispatch § Fragmented instance data

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory:

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory: binds data @ compile time o Performance: poor cache coherence o Architecture: capability <=> inheritance § Fixed at compile time § Fully determined by class § Change capabilities -> change hierarchy

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory:

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory: binds data @ compile time o Performance: poor cache coherence o Architecture: capability <=> inheritance • "What we're used to" • But select the best tool for the job.

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory:

Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory: binds data @ compile time o Performance: poor cache coherence o Architecture: capability <=> inheritance • "What we're used to" • But select the best tool for the job. • There's a better way!

A Dynamic Component Architecture for High Performance Gameplay • Purpose o Statement of Problem

A Dynamic Component Architecture for High Performance Gameplay • Purpose o Statement of Problem o Proposed Solution • The Dynamic Component System • Implementation by Example

Purpose : Proposed Solution • Construction of Game Object through composition of components at

Purpose : Proposed Solution • Construction of Game Object through composition of components at runtime

Purpose : Proposed Solution • Construction of Game Object through composition of components at

Purpose : Proposed Solution • Construction of Game Object through composition of components at runtime • Simple! • Thank you for coming!

Purpose : Proposed Solution • Construction of Game Object through composition of components at

Purpose : Proposed Solution • Construction of Game Object through composition of components at runtime • Simple! • Thank you for coming! o Oh, you want details !? !

Purpose : Proposed Solution • Construction of Game Object through composition of components at

Purpose : Proposed Solution • Construction of Game Object through composition of components at runtime • Small chunks • Represent a data transformation

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System o Features • Implementation by Example

The Dynamic Component System • Evolution o Resistance 1 - Proof of Concept (1

The Dynamic Component System • Evolution o Resistance 1 - Proof of Concept (1 type) o Resistance 2 - "Early Adopters" (32 types) o Ongoing (295 types as of May 1 st 2010) § Majority of new gameplay code § Large portions of old gameplay refactored

The Dynamic Component System • Evolution o Resistance 1 - Proof of Concept (1

The Dynamic Component System • Evolution o Resistance 1 - Proof of Concept (1 type) o Resistance 2 - "Early Adopters" (32 types) o Ongoing (295 types as of May 1 st 2010) § Majority of new gameplay code § Large portions of old gameplay refactored • So it’s mature.

The Dynamic Component System • Evolution o Resistance 1 - Proof of Concept (1

The Dynamic Component System • Evolution o Resistance 1 - Proof of Concept (1 type) o Resistance 2 - "Early Adopters" (32 types) o Ongoing (295 types as of May 1 st 2010) § Majority of new gameplay code § Large portions of old gameplay refactored • So it’s mature. (No, not that way. )

The Dynamic Component System • Side-by-side implementation o Not necessary to refactor existing code

The Dynamic Component System • Side-by-side implementation o Not necessary to refactor existing code o Coexist with components • General solution

The Dynamic Component System • Does not address matters of o Reflection o Serialization

The Dynamic Component System • Does not address matters of o Reflection o Serialization o Data building o Instance versioning o. . . those things are handled separately § outside the scope of this discussion

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System o Features • Implementation by Example

Dynamic Component System : Features • Components • High-performance • Dynamic • System

Dynamic Component System : Features • Components • High-performance • Dynamic • System

Dynamic Component System : Features • Components o Originally Aspects o Base Component class

Dynamic Component System : Features • Components o Originally Aspects o Base Component class § 8 bytes of administrative data o Allocated from pools § One pool per concrete type § "Roster" indexes instances § "Partition" separates allocated/free instances

Dynamic Component System : Features • Components • High-performance o Small, constant-time operations §

Dynamic Component System : Features • Components • High-performance o Small, constant-time operations § Allocate/free § Resolve handle § Get type § Type implements (derived from) o No instance copying

Dynamic Component System : Features • Components • High-performance o Updates per-type (per-pool) §

Dynamic Component System : Features • Components • High-performance o Updates per-type (per-pool) § Cache friendly o Encourage async update § e. g. on SPU § Roster: contiguous list of alloc'd instances § Roster up to partition is DMA list

Dynamic Component System : Features • Components • High-performance o Resolving handle § Small,

Dynamic Component System : Features • Components • High-performance o Resolving handle § Small, constant-time operation: § Index into Pool § Compare generation § Return Component*

Dynamic Component System : Features • Components • High-performance • Dynamic o Runtime composition

Dynamic Component System : Features • Components • High-performance • Dynamic o Runtime composition of game objects § Dynamically alter behavior without baggage o Component allocated == in use o Pool sizes == max concurrent allocations

Dynamic Component System : Features • Components • High-performance • Dynamic o High-frequency alloc()

Dynamic Component System : Features • Components • High-performance • Dynamic o High-frequency alloc() & free() § alloc(): § test for availability § make handle from index & generation § increment Roster Partition § Component: : Init()

Dynamic Component System : Features • Components • High-performance • Dynamic o High-frequency alloc()

Dynamic Component System : Features • Components • High-performance • Dynamic o High-frequency alloc() & free() § alloc(): § free(): § Component: : Deinit() § swap Roster index with Partition-adjacent index § decrement Partition § increment generation

Demo : Dynamic. Component: : Free() //free the component from host's component chain void

Demo : Dynamic. Component: : Free() //free the component from host's component chain void Dynamic. Component: : Free( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle );

Demo : Dynamic. Component: : Free() //free the component from host's component chain void

Demo : Dynamic. Component: : Free() //free the component from host's component chain void Dynamic. Component: : Free( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle );

Demo : Dynamic. Component: : Free() //free the component from host's component chain void

Demo : Dynamic. Component: : Free() //free the component from host's component chain void Dynamic. Component: : Free( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle );

Demo : Dynamic. Component: : Free() //free the component from host's component chain void

Demo : Dynamic. Component: : Free() //free the component from host's component chain void Dynamic. Component: : Free( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle );

Demo : Dynamic. Component: : Free() //free the component from host's component chain void

Demo : Dynamic. Component: : Free() //free the component from host's component chain void Dynamic. Component: : Free( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle );

Dynamic Component System : Features • • Components High-performance Dynamic System o Not all-or-nothing!

Dynamic Component System : Features • • Components High-performance Dynamic System o Not all-or-nothing! o Examples: § Conversation § Script Events § Shots: no game object

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example o API o Script Events: Type Registration o Navigation: Allocation & Init o Shots: Asynchronous Update

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or other objects) that host Dynamic Components // __________________________________________________ //allocate a component of type, add it to host's component chain, // and optionally park a prius in the component // returns null if no space is available for allocation Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL );

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); __________________________________________________ //resolve a Component. Handle to a Component // returns NULL if component_handle is null or is a stale handle // (i. e. component instance has been reused) Component* Resolve. Handle ( Type type, Component. Handle component_handle );

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); __________________________________________________ //get one component of type that belongs to host Component* Get ( Type type, Host. Handle host_handle, Chain chain );

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); __________________________________________________ //get the first Component in host's chain that implements the type interface Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain );

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); __________________________________________________ //get all Components of type in host's chain, up to a max of count instances. // count should be passed with the size of the component array. // on return, count will contain the number of matching components, up to the specified limit. Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count );

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); __________________________________________________ //get all Components in host's chain that implement type's interface. // count should be passed with the size of the component array. // on return, count will contain the number of matching components, up to the specified limit. Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count );

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); __________________________________________________ //free the component from host's component chain void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle );

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); __________________________________________________ //free all of the components in host's component chain // (Game. Objects automatically free their component chain when they are destroyed) void Free. Chain ( Host. Handle host_handle, Chain& chain );

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or

namespace Dynamic. Component { // Hosts' API // Call these from Game. Objects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); __________________________________________________ //downcast a Component* to one of its subclasses. // please use this instead of the c-style '(Type*)object' so that casts are checked in debug //Example: // Head. Component* my_head = COMPONENT_CAST(component_ptr, Head); // #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type );

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type ); __________________________________________________ // // Systems' API // Call these from systems that use the DCS // //get a list of component types that implement the interface of the given component type // count should be passed with the size of the types array. // on return, count will contain the number of matching component types, // up to the specified limit. Type* Get. Types. That. Implement ( Type type, u 32& count );

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type ); // // Systems' API // Call these from systems that use the DCS // Type* Get. Types. That. Implement ( Type type, u 32& count ); __________________________________________________ //returns whether component type implements interface bool Type. Implements ( Type type, Type interface );

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type ); // // Systems' API // Call these from systems that use the DCS // Type* Get. Types. That. Implement ( Type type, u 32& count ); bool Type. Implements ( Type type, Type interface ); __________________________________________________ //returns the number of components of type that are currently allocated u 32 Get. Num. Allocated ( Type type );

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type ); // // Systems' API // Call these from systems that use the DCS // Type* Get. Types. That. Implement ( Type type, u 32& count ); bool Type. Implements ( Type type, Type interface ); u 32 Get. Num. Allocated ( Type type ); __________________________________________________ //returns an array of pointers to allocated components of type, their count, // and their size Component** Get. Components ( Type type, u 32& count ); //returns an array of all components of type (including unallocated instances!), // an array of the indices of allocated components within that array, // and the count of indices Component* Get. Components. Indexed ( Type type, u 16*& indices, u 32& count );

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type ); // // Systems' API // Call these from systems that use the DCS // Type* Get. Types. That. Implement ( Type type, u 32& count ); bool Type. Implements ( Type type, Type interface ); u 32 Get. Num. Allocated ( Type type ); Component** Get. Components ( Type type, u 32& count ); Component* Get. Components. Indexed ( Type type, u 16*& indices, u 32& count ); __________________________________________________ //updates all components of those types that want to be updated in the given Update. Stage void Update. Components ( Update. Stage: : Enum stage );

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type ); // // Systems' API // Call these from systems that use the DCS // Type* Get. Types. That. Implement ( Type type, u 32& count ); bool Type. Implements ( Type type, Type interface ); u 32 Get. Num. Allocated ( Type type ); Component** Get. Components ( Type type, u 32& count ); Component* Get. Components. Indexed ( Type type, u 16*& indices, u 32& count ); void Update. Components ( Update. Stage: : Enum stage ); __________________________________________________ //frees a component that was allocated without a host, and is not in any chain void Free ( Type type, Component. Handle& component_handle );

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type ); // // Systems' API // Call these from systems that use the DCS // Type* Get. Types. That. Implement ( Type type, u 32& count ); bool Type. Implements ( Type type, Type interface ); u 32 Get. Num. Allocated ( Type type ); Component** Get. Components ( Type type, u 32& count ); Component* Get. Components. Indexed ( Type type, u 16*& indices, u 32& count ); void Update. Components ( Update. Stage: : Enum stage ); void Free ( Type type, Component. Handle& component_handle ); __________________________________________________ //returns the current PPU Update. Stage: : Enum. // will be Update. Stage: : None unless Update. Components() is on the stack. Update. Stage: : Enum Get. Current. Update. Stage ( );

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type ); // // Systems' API // Call these from systems that use the DCS // Type* Get. Types. That. Implement ( Type type, u 32& count ); bool Type. Implements ( Type type, Type interface ); u 32 Get. Num. Allocated ( Type type ); Component** Get. Components ( Type type, u 32& count ); Component* Get. Components. Indexed ( Type type, u 16*& indices, u 32& count ); void Update. Components ( Update. Stage: : Enum stage ); void Free ( Type type, Component. Handle& component_handle ); Update. Stage: : Enum Get. Current. Update. Stage ( ); __________________________________________________ //returns true iff type updates in stage u 8 Get. Type. Update. Stages ( Type type ); }

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle

namespace Dynamic. Component { // Hosts' API Component* Allocate ( Type type, Host. Handle host_handle, Chain* chain, void* prius = NULL ); Component* Resolve. Handle ( Type type, Component. Handle component_handle ); Component* Get ( Type type, Host. Handle host_handle, Chain chain ); Component* Get. Component. That. Implements( Type type, Host. Handle host_handle, Chain chain ); Component** Get. Components ( Type type, Host. Handle host_handle, Chain chain, u 32& count ); Component** Get. Components. That. Implement( Type type, Host. Handle host_handle, Chain chain, u 32& count ); void Free ( Type type, Host. Handle host_handle, Chain& chain, Component. Handle& component_handle ); void Free. Chain ( Host. Handle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)Valid. Cast(component, Dynamic. Component: : type)) inline Component* Valid. Cast ( Component* component, Type type ); // Systems' API Type* Get. Types. That. Implement ( Type type, u 32& count ); bool Type. Implements ( Type type, Type interface ); u 32 Get. Num. Allocated ( Type type ); Component** Get. Components ( Type type, u 32& count ); Component* Get. Components. Indexed ( Type type, u 16*& indices, u 32& count ); void Update. Components ( Update. Stage: : Enum stage ); void Free ( Type type, Component. Handle& component_handle ); Update. Stage: : Enum Get. Current. Update. Stage ( ); u 8 Get. Type. Update. Stages ( Type type ); }

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example o API o Script Events: Type Registration o Navigation: Allocation & Init o Shots: Asynchronous Update

Script Events : Type Registration • Script Events are Components o Hosted by the

Script Events : Type Registration • Script Events are Components o Hosted by the System o Possibly related to a Game Object • Registered (allocated) from Lua o When conditions are met, call back • Satisfaction: 1. Updated: poll their conditions 2. Notified by gameplay

Script Events : Type Registration Notified Updated • • Location • Timer • Visible

Script Events : Type Registration Notified Updated • • Location • Timer • Visible Checkpoint Damage Death Num. Alive Active Custom o Reload o Zoom o Grapple o Seat. Enter

Script Events: Type Registration namespace Dynamic. Component { typedef u 16 Type; Type unregistered_type

Script Events: Type Registration namespace Dynamic. Component { typedef u 16 Type; Type unregistered_type = 0 x. FFFF; Type. Registrar: : Register. Type( const char* name, Type base_type = unregistered_type, Update. Stage: : Enum update_stages = Update. Stage: : None, Async. Update. Stage: : Enum async_update_stages = Async. Update. Stage: : None); }

Script Events: Type Registration namespace Dynamic. Component { typedef u 16 Type; Type unregistered_type

Script Events: Type Registration namespace Dynamic. Component { typedef u 16 Type; Type unregistered_type = 0 x. FFFF; Type. Registrar: : Register. Type( const char* name, Type base_type = unregistered_type, Update. Stage: : Enum update_stages = Update. Stage: : None, Async. Update. Stage: : Enum async_update_stages = Async. Update. Stage: : None); } using namespace Dynamic. Component; void Script. Event. System: : Init() { m_event_type = Type. Registrar: : Register. Type("Script. Event"); m_checkpoint_type = Type. Registrar: : Register. Type("Checkpoint. Event", m_event_type); m_location_type = Type. Registrar: : Register. Type( "Location. Event", m_event_type, //base class is Script. Event Update. Stage: : Post. Update, //automatically updated on PPU during Post. Update Async. Update. Stage: : Pre. Update); //and on the SPU during the Pre. Update stage }

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example o API o Script Events: Type Registration o Navigation: Allocation & Init o Shots: Asynchronous Update

Navigation : Allocation & Initialization • Nav. Components are hosted by Game Objects •

Navigation : Allocation & Initialization • Nav. Components are hosted by Game Objects • Updated by the Navigation system

Navigation : Allocation & Initialization • Remember the API call to allocate a component:

Navigation : Allocation & Initialization • Remember the API call to allocate a component: //allocate a component of type, add it to host's component chain, // and optionally park a prius in the component // returns null if no space is available for allocation Component* Dynamic. Component: : Allocate( Type type, Host. Handle host_handle, Chain* chain, void* • WTF is a prius? prius = NULL );

Navigation : Allocation & Initialization • Remember the API call to allocate a component:

Navigation : Allocation & Initialization • Remember the API call to allocate a component: //allocate a component of type, add it to host's component chain, // and optionally park a prius in the component // returns null if no space is available for allocation Component* Dynamic. Component: : Allocate( Type type, Host. Handle host_handle, Chain* chain, void* • WTF is a prius? o initialization data o Runtime or design-time data • void* But is that safe!? prius = NULL );

Navigation : Allocation & Initialization • Initialization o Nav. Query is the Prius for

Navigation : Allocation & Initialization • Initialization o Nav. Query is the Prius for a Nav. Component o Nav. Query: : Submit() allocates a Nav. Component, and passes itself as the prius. Nav. Component* Nav. Query: : Submit(Game. Object* host) { Dynamic. Component: : Type type = Get. Component. Type(); //virtual member of Nav. Query Dynamic. Component: : Component* component = host->Allocate. Component(type, this); Nav. Component* nav = COMPONENT_CAST(component, Nav); return nav; } • host->Allocate. Component()? Helper in Game. Object: Dynamic. Component* Game. Object: : Allocate. Component(Dynamic. Component: : Type type, void* prius) { return Dynamic. Component: : Allocate(type, m_handle, &m_component_chain, prius); }

Navigation : Allocation & Initialization • Gameplay code example void Follower. Bot: : Initialize(Game.

Navigation : Allocation & Initialization • Gameplay code example void Follower. Bot: : Initialize(Game. Object* target) { Nav: : Game. Object. Query source_query (this); //query closest point to game object Nav: : Game. Object. Query target_query (target); Nav: : Path. Query path_query (source_query, target_query); Nav: : Path. Component* m_path = path_query. Submit(); } • When navigation components are updated, endpoints and path are dynamically recomputed on SPU

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example o API o Script Events: Type Registration o Navigation: Allocation & Init o Shots: Asynchronous Update

Shots : Asynchronous Update • Hosted by Game Object • Replaces Projectile Game. Objects

Shots : Asynchronous Update • Hosted by Game Object • Replaces Projectile Game. Objects • Two Dynamic. Component Type hierarchies: o Shot represents a state machine § Notified o Shot. Action represents the state of a Shot § Updated § Shared

Shots : Asynchronous Update #ifndef SPU //PPU only class Shot. Move. Forward : public

Shots : Asynchronous Update #ifndef SPU //PPU only class Shot. Move. Forward : public Shot. Action { DERIVED_COMPONENT(Shot. Move. Forward, Shot. Action) public: virtual void Park. Prius (void* prius); virtual void Update (Update. Stage: : Enum stage); #else //SPU only struct Shot. Move. Forward { puspu_vec 4 m_location ALIGNED(16); //shadows Shot. Action: : m_next_location on PPU #endif //PPU & SPU shared puspu_vec 4 m_direction; f 32 m_speed; } __attribute__((aligned(16))); PPU and Shot. Move. Forward: : m_location on SPU share the same address • Shot. Action: : m_next_location on

Shots : Asynchronous Update • How? "Sentinel" // async components must indicate where their

Shots : Asynchronous Update • How? "Sentinel" // async components must indicate where their async data begins #define BEGIN_ASYNC_COMPONENT_DATA u 32 m_async_data[0] __attribute__((aligned(16))); class Shot. Action : public Dynamic. Component: : Component { COMPONENT(Shot. Action); //. . . Dynamic. Component: : Handle m_shot; Dynamic. Component: : Type m_shot_type; BEGIN_ASYNC_COMPONENT_DATA vec 4 f m_next_location; };

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component

A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example • Thank You! • Questions

A Dynamic Component Architecture for High Performance Gameplay • Visit me on the Web:

A Dynamic Component Architecture for High Performance Gameplay • Visit me on the Web: http: //www. Terrance. Cohen. com • Follow me on Twitter: http: //twitter. com/terrance_cohen • Connect with me on Linked. In: http: //www. linkedin. com/in/terrancecohen • Ask me anything: http: //www. formspring. me/terrancecohen

A Dynamic Component Architecture for High Performance Gameplay Terrance Cohen Lead Systems Engineer Insomniac

A Dynamic Component Architecture for High Performance Gameplay Terrance Cohen Lead Systems Engineer Insomniac Games www. Terrance. Cohen. com Twitter: @terrance_cohen