Transitioning to Native
Robbie Litchfield
Software Engineer
Grinding Gear Games
Motivation
Motivation
● Engines have their limits.
● C/C++ usage in indie middleware.
● Programmer control over tech.
● Pushing target platform performance.
Agenda
● Jumping into Native Development.
● Development without an Editor.
● Memory Management without GC.
Jumping into Native
Development
Jumping into Native Development
“A Curiously Repeating Story”
By Robbie Litchfield
Jumping into Native Development
Day 1:
● Find C++ materials.
● Open StackOverflow.
● Write some code.
Jumping into Native Development
Week 1:
● Start on game idea.
● Powering through problems.
● Diligent StackOverflow use.
● Perceived leaps and bounds.
Jumping into Native Development
Month 1:
● StackOverflow
 :(
● Errors are alien.
● Progress is dwindling.
● C++ love affair is over.
Jumping into Native Development
Many moons later:
● Minimal to no progress.
● Project seems ill-defined.
● Longing thoughts of Unity.
● Project failure.
Jumping into Native Development
“Going Native” for the wrong reasons.
Jumping into Native Development
● Understand your own requirements.
● Make pragmatic risk/benefit analyses.
● Explore novel solutions with existing tools.
● Do the above *before* cutting code.
Jumping into Native Development
Attempting too much, too soon, too fast.
Jumping into Native Development
● Start out on small and simple pilot projects.
● Take time for learning, analysis and design.
● Extend project time estimates, double them.
Jumping into Native Development
Confusing training with skill.
Jumping into Native Development
● “Yeah, I’m sure I can pick up C++ quickly.”
● Use introspection, plan around skillsets.
● Push through, skills come from experience.
● Invest in fostering talent in your team.
Jumping into Native Development
Your mileage may vary.
Development without
an Editor
Development without an Editor
The bad old days.
Development without an Editor
● Games were largely hard coded.
● Tools, if any, were primitive.
● Games typically had miniscule content.
Development without an Editor
Today.
Development without an Editor
● Games are larger and more complex.
● Demand for high content games.
● The standard for quality keeps on rising.
● Game sizes growing faster than teams.
Development without an Editor
Development without an Editor
Development without an Editor
Development without an Editor
Programmer time is a large bottleneck.
class Monster : GameObject, MRenderable
{
Monster(Health_t health);
virtual Attack_t GetAttack( ) = 0;
Health_t m_Health;
};
Development without an Editor
class Dragon : Monster
{
Dragon( ) : Monster( 99 ) {
}
virtual void GetAttack( ) override {
return “The dragon’s fire results in a
swift death.”; }
};
Development without an Editor
1. Designer asks for trivial change in Dragon.h
2. Modify Dragon.h
3. Recompile and check-in changes.
4. Reply to designer.
Development without an Editor
Development without an Editor
Data Driven Development
Development without an Editor
● Empower those who make the decisions.
● Minimise iteration time with powerful tools.
● Data requirements drive software design.
Development without an Editor
Data Driven Game Objects
{
“Name” : “DemonDragon”,
“Prototype” : “Dragon”,
“Attacks” : [ “SummonLesserDragons”,
“CharmMinion”, “MightyClaw”, “FireBreath” ]
“MinHealth” : “1500”
}
Development without an Editor
Game ObjectMRenderableMControllable MAnimatable
Actor
Monster
Development without an Editor
Monster
Demon
Dragon
“Attacks”
“MinHealth”“Zone”
Monster(Json &json) {
m_Health = json[“MinHealth”];
m_Attacks = json[“Attacks”];
m_Zone = json[“Zone”];
}
Development without an Editor
Monster
Goblin ElfDragon Human
TrollBlackDragon HighElf Orc
Demon
Dragon
Development without an Editor
● Works well if types are similar.
● Can’t express complex hierarchies.
● Still requires programmer time.
● We can do better...
Development without an Editor
Game Object PrototypeMonster
Script
Render
Development without an Editor
class GameObject
{
public:
GameObject( Id_t id );
Id_t m_Id;
Id_t m_Prototype;
IntrusiveList<Component> m_Components;
};
Development without an Editor
MonsterDemon
Dragon
“Attacks”
“MinHealth”
“Zone”
Actor
GameObject
GameObject* Create(Json &json) {
for(auto& p : json) {
// Select component for property
// Set component value
}
}
Development without an Editor
● Added runtime cost.
● Compiler can’t help with type checking.
● Can trivially create new types without code.
● Programmer time for new concepts.
Development without an Editor
● Materials
● Scripts
● User Displayed Strings
● So much more...
Development without an Editor
● Tools take time to develop and maintain.
● Not everything needs to be data driven.
● Text files can often be enough.
● Be prepared to refactor toolchain.
Memory Management
without GC
GC Memory Management
void CSharp( )
{
var val = new T(“NZGDA”);
/** ... **/
val = null; /* Optional */
}
Memory Management without GC
Memory Management without GC
● Convenient.
● Non-deterministic cleanup.
● Non-deterministic performance.
● C/C++ GC support is a kludge.
Memory Management without GC
Manual Memory Management
Stack Heap
Memory Management without GC
Manual Memory Management
void Func( ) {
int val = 5;
/** ... **/
}
Memory Management without GC
Manual Memory Management
void Func( ) {
auto *ptr = new T(“NZGDC15”);
/** ... **/
delete ptr;
}
Memory Management without GC
T* ptr;
● Lifetime?
● Ownership?
● Cleanup?
● Safety?
Memory Management without GC
“Resource Acquisition Is Initialization”
Memory Management without GC
R.A.I.I.
● Resource is bound to an object’s lifetime.
● Constructor performs resource acquisition.
● Destructor performs resource destruction.
Memory Management without GC
R.A.I.I. Smart Pointers
class scoped_ptr {
scoped_ptr ( int* p ) { m_ptr = p; }
~scoped_ptr ( ) { delete m_ptr; }
int* m_ptr;
/** ... **/
};
Memory Management without GC
R.A.I.I. Smart Pointers
void Function( )
{
scoped_ptr ptr( new int );
// Memory at ptr destroyed here
}
Memory Management without GC
R.A.I.I. Smart Pointers
● std::unique_ptr<T>
● std::shared_ptr<T>
● std::weak_ptr<T>
Memory Management without GC
● Superior to manual memory management.
● Deterministic cleanup and performance.
● Useful for any system resource.
● Learn this pattern, it’s everywhere.
C/C++ Dynamic Memory
void Func( ) {
auto *ptr = new T(“NZGDC15”);
/** ... **/
delete ptr;
}
Memory Management without GC
Memory Management without GC
● Global State.
● Slow, Heavy Subsystem.
● Virtual Memory Limitations.
● Heap Fragmentation.
Memory Management without GC
Heap Fragmentation
Memory Management without GC
Allocators
Memory Management without GC
Stack Alloc Alloc Alloc Alloc
Stack Heap
Memory Management without GC
● Give up some convenience.
● Faster than the runtime heap.
● Fragmentation can be eliminated.
● Games only need a couple patterns...
Memory Management without GC
Default Allocator
malloc() free()
Memory Management without GC
● Simple adaptor around runtime heap.
● Helps with bootstrapping allocator usage.
● Avoid use in production builds.
Memory Management without GC
Stack Allocator
Alloc Free
Alloc FreeAlloc
Memory Management without GC
● Games already behave like a stack.
● Trivial to implement.
● Fragmentation proof.
● Strong ordering requirements.
Memory Management without GC
Object Pool Allocator
Free Free Free Free Free
Alloc Free Alloc Free Free
Memory Management without GC
● Suitable for game simulation data.
● Subtle implementation issues.
● Fragmentation proof.
● No ordering requirements.
Memory Management without GC
● Games can be made with the runtime heap.
● Allocators are hard to debug.
● Another tool in the toolbox.
Thanks!
robbie.l@missingbox.co.nz
www.github.com/regretbomb

Transitioning to Native

  • 1.
    Transitioning to Native RobbieLitchfield Software Engineer Grinding Gear Games
  • 2.
  • 3.
    Motivation ● Engines havetheir limits. ● C/C++ usage in indie middleware. ● Programmer control over tech. ● Pushing target platform performance.
  • 4.
    Agenda ● Jumping intoNative Development. ● Development without an Editor. ● Memory Management without GC.
  • 5.
  • 6.
    Jumping into NativeDevelopment “A Curiously Repeating Story” By Robbie Litchfield
  • 7.
    Jumping into NativeDevelopment Day 1: ● Find C++ materials. ● Open StackOverflow. ● Write some code.
  • 8.
    Jumping into NativeDevelopment Week 1: ● Start on game idea. ● Powering through problems. ● Diligent StackOverflow use. ● Perceived leaps and bounds.
  • 9.
    Jumping into NativeDevelopment Month 1: ● StackOverflow
 :( ● Errors are alien. ● Progress is dwindling. ● C++ love affair is over.
  • 10.
    Jumping into NativeDevelopment Many moons later: ● Minimal to no progress. ● Project seems ill-defined. ● Longing thoughts of Unity. ● Project failure.
  • 11.
    Jumping into NativeDevelopment “Going Native” for the wrong reasons.
  • 12.
    Jumping into NativeDevelopment ● Understand your own requirements. ● Make pragmatic risk/benefit analyses. ● Explore novel solutions with existing tools. ● Do the above *before* cutting code.
  • 13.
    Jumping into NativeDevelopment Attempting too much, too soon, too fast.
  • 14.
    Jumping into NativeDevelopment ● Start out on small and simple pilot projects. ● Take time for learning, analysis and design. ● Extend project time estimates, double them.
  • 15.
    Jumping into NativeDevelopment Confusing training with skill.
  • 16.
    Jumping into NativeDevelopment ● “Yeah, I’m sure I can pick up C++ quickly.” ● Use introspection, plan around skillsets. ● Push through, skills come from experience. ● Invest in fostering talent in your team.
  • 17.
    Jumping into NativeDevelopment Your mileage may vary.
  • 18.
  • 19.
    Development without anEditor The bad old days.
  • 20.
    Development without anEditor ● Games were largely hard coded. ● Tools, if any, were primitive. ● Games typically had miniscule content.
  • 21.
  • 22.
    Development without anEditor ● Games are larger and more complex. ● Demand for high content games. ● The standard for quality keeps on rising. ● Game sizes growing faster than teams.
  • 23.
  • 24.
  • 25.
  • 26.
    Development without anEditor Programmer time is a large bottleneck. class Monster : GameObject, MRenderable { Monster(Health_t health); virtual Attack_t GetAttack( ) = 0; Health_t m_Health; };
  • 27.
    Development without anEditor class Dragon : Monster { Dragon( ) : Monster( 99 ) { } virtual void GetAttack( ) override { return “The dragon’s fire results in a swift death.”; } };
  • 28.
    Development without anEditor 1. Designer asks for trivial change in Dragon.h 2. Modify Dragon.h 3. Recompile and check-in changes. 4. Reply to designer.
  • 29.
  • 30.
    Development without anEditor Data Driven Development
  • 31.
    Development without anEditor ● Empower those who make the decisions. ● Minimise iteration time with powerful tools. ● Data requirements drive software design.
  • 32.
    Development without anEditor Data Driven Game Objects { “Name” : “DemonDragon”, “Prototype” : “Dragon”, “Attacks” : [ “SummonLesserDragons”, “CharmMinion”, “MightyClaw”, “FireBreath” ] “MinHealth” : “1500” }
  • 33.
    Development without anEditor Game ObjectMRenderableMControllable MAnimatable Actor Monster
  • 34.
    Development without anEditor Monster Demon Dragon “Attacks” “MinHealth”“Zone” Monster(Json &json) { m_Health = json[“MinHealth”]; m_Attacks = json[“Attacks”]; m_Zone = json[“Zone”]; }
  • 35.
    Development without anEditor Monster Goblin ElfDragon Human TrollBlackDragon HighElf Orc Demon Dragon
  • 36.
    Development without anEditor ● Works well if types are similar. ● Can’t express complex hierarchies. ● Still requires programmer time. ● We can do better...
  • 37.
    Development without anEditor Game Object PrototypeMonster Script Render
  • 38.
    Development without anEditor class GameObject { public: GameObject( Id_t id ); Id_t m_Id; Id_t m_Prototype; IntrusiveList<Component> m_Components; };
  • 39.
    Development without anEditor MonsterDemon Dragon “Attacks” “MinHealth” “Zone” Actor GameObject GameObject* Create(Json &json) { for(auto& p : json) { // Select component for property // Set component value } }
  • 40.
    Development without anEditor ● Added runtime cost. ● Compiler can’t help with type checking. ● Can trivially create new types without code. ● Programmer time for new concepts.
  • 41.
    Development without anEditor ● Materials ● Scripts ● User Displayed Strings ● So much more...
  • 42.
    Development without anEditor ● Tools take time to develop and maintain. ● Not everything needs to be data driven. ● Text files can often be enough. ● Be prepared to refactor toolchain.
  • 43.
  • 44.
    GC Memory Management voidCSharp( ) { var val = new T(“NZGDA”); /** ... **/ val = null; /* Optional */ } Memory Management without GC
  • 45.
    Memory Management withoutGC ● Convenient. ● Non-deterministic cleanup. ● Non-deterministic performance. ● C/C++ GC support is a kludge.
  • 46.
    Memory Management withoutGC Manual Memory Management Stack Heap
  • 47.
    Memory Management withoutGC Manual Memory Management void Func( ) { int val = 5; /** ... **/ }
  • 48.
    Memory Management withoutGC Manual Memory Management void Func( ) { auto *ptr = new T(“NZGDC15”); /** ... **/ delete ptr; }
  • 49.
    Memory Management withoutGC T* ptr; ● Lifetime? ● Ownership? ● Cleanup? ● Safety?
  • 50.
    Memory Management withoutGC “Resource Acquisition Is Initialization”
  • 51.
    Memory Management withoutGC R.A.I.I. ● Resource is bound to an object’s lifetime. ● Constructor performs resource acquisition. ● Destructor performs resource destruction.
  • 52.
    Memory Management withoutGC R.A.I.I. Smart Pointers class scoped_ptr { scoped_ptr ( int* p ) { m_ptr = p; } ~scoped_ptr ( ) { delete m_ptr; } int* m_ptr; /** ... **/ };
  • 53.
    Memory Management withoutGC R.A.I.I. Smart Pointers void Function( ) { scoped_ptr ptr( new int ); // Memory at ptr destroyed here }
  • 54.
    Memory Management withoutGC R.A.I.I. Smart Pointers ● std::unique_ptr<T> ● std::shared_ptr<T> ● std::weak_ptr<T>
  • 55.
    Memory Management withoutGC ● Superior to manual memory management. ● Deterministic cleanup and performance. ● Useful for any system resource. ● Learn this pattern, it’s everywhere.
  • 56.
    C/C++ Dynamic Memory voidFunc( ) { auto *ptr = new T(“NZGDC15”); /** ... **/ delete ptr; } Memory Management without GC
  • 57.
    Memory Management withoutGC ● Global State. ● Slow, Heavy Subsystem. ● Virtual Memory Limitations. ● Heap Fragmentation.
  • 58.
    Memory Management withoutGC Heap Fragmentation
  • 59.
  • 60.
    Memory Management withoutGC Stack Alloc Alloc Alloc Alloc Stack Heap
  • 61.
    Memory Management withoutGC ● Give up some convenience. ● Faster than the runtime heap. ● Fragmentation can be eliminated. ● Games only need a couple patterns...
  • 62.
    Memory Management withoutGC Default Allocator malloc() free()
  • 63.
    Memory Management withoutGC ● Simple adaptor around runtime heap. ● Helps with bootstrapping allocator usage. ● Avoid use in production builds.
  • 64.
    Memory Management withoutGC Stack Allocator Alloc Free Alloc FreeAlloc
  • 65.
    Memory Management withoutGC ● Games already behave like a stack. ● Trivial to implement. ● Fragmentation proof. ● Strong ordering requirements.
  • 66.
    Memory Management withoutGC Object Pool Allocator Free Free Free Free Free Alloc Free Alloc Free Free
  • 67.
    Memory Management withoutGC ● Suitable for game simulation data. ● Subtle implementation issues. ● Fragmentation proof. ● No ordering requirements.
  • 68.
    Memory Management withoutGC ● Games can be made with the runtime heap. ● Allocators are hard to debug. ● Another tool in the toolbox.
  • 69.