Who am I

backgr

Valentin Galea - @valentin_galea
more than 10 years doing mobile, indie and AAA games

Games worked on

Currently at Splash Damage in London, UK

Agenda

  • Types of video games
  • The industry
  • Philosophy
  • Platform
  • Flavours of C++
  • OOP & Alternatives
  • Templates
  • STL & Boost
  • Exceptions
  • Reflection & RTTI
  • Conclusions

Types of games - AAA

AAA games […] informal classification used for video games with the highest development budgets and levels of promotion
— Wikipedia
AAA games

Types of games - indie

indie games […] created without the financial support of a publisher
— Wikipedia
indie games

Types of games - mobile

mobile games […] played on a feature phone, smartphone, smartwatch, PDA, tablet computer
— Wikipedia
mobile games

What I will talk about

Mostly about AAA games

  • I have the most experience with recently
  • they are the most process driven
  • use C++ in very special and quirky ways (the purpose of the talk)

Indie games

  • they share some elements with the above, but is in general more straightforward

Mobile games

  • usually written in something else: Objective C, C# - but they also do idiomatic C++

What I won’t talk about

Scripting languages

  • normally AAA games supplement the C++ with another language for gameplay and level scripting
    • Lua, Python, etc
    • custom made: UnrealScript, DSL’s, etc
  • Visual scripting spaghetti
    • UE4 "blueprints" 1
    • Guerilla Games Nodegraph system 2

Tools

  • can be written in C++, but a lot of them are in C# or Python

Building / Packaging game data

  • a nightmare on its own

The industry - It’s a secret

Secret

For various reasons, AAA development is covered in secrecy, source code included

The industry (2)

Some of these reasons…

  • IP principles and copyright
  • "first to market" desire and competition
  • multiple stakeholders involved

id software notably broke the trend and released the source code of all their Doom and Quake games

The rest of the industry didn’t follow suit. Even id stopped after being acquired by the publisher Bethesda

The industry (3)

Some modern AAA game engines changed their licensing and they’re now open…

Studios sometimes release internal libraries for general use
EA/EASTL, InsomniacGames/ig-cachesim, Remedy-Entertainment/binderoo etc

Note
Everything here based on my experience so far, YMMV!
Note
I will unfairly concentrate on Epic’s UE4 :)
* I worked with it for the past years
* It does a lot of C++ questionable things

A glimpse of good

Source code snippet from Doom 3

Doom 3 src

A glimpse of bad

Source code snippet from CryEngine

CryEngine 3 src
backgr

Philosophy / Platform / Compilation

Philosophy

Games need to run

  • at least 30 FPS - 33 ms per frame
  • 60+ FPS very desirable (obligatory for good multiplayer) - 16 ms per frame

Everything is centered around achieving this - while…

  • pushing the graphics and gameplay
  • maintaining low-latency

Tradeoffs…

  • stability is important
    • a (rare) crash forgiven if it doesn’t corrupt the save/user data
  • limited concern for uptime
    • unless server
    • unless it leaks over time!
  • low-latency but throughput also important - got to push millions of pixels to the screen!

Project size/LOC

AAA studios…

  • hundreds of people across various continents
  • lots of wheel reinventions
  • legacy of franchise games and sequels

…so amount of code quickly skyrockets…

Assassin’s Creed Unity:

  • 6.5 M C++ LOC for entire team code.
  • 9 M more C++ LOC from outside project.

Rainbow Six: Siege:

  • 3.5 M C++ LOC for engine code from game team.
  • 4.5 M C++ LOC from Technology Group.
— CppCon 2014: Nicolas Fleury "C++ in Huge AAA Games"

Platform - Compiler

By far and large Windows centric development - even for consoles

MSVC

  • is overwhelmingly used, almost de facto standard
  • sometimes quite old versions, by now 2013+
  • before C++11 lots of code depended on Microsoft quirks

GCC

  • rarely used on PC : mainly dedicated servers, or the odd Linux port
  • prev gen consoles had vendor specific variants

clang

  • Playstation 4® uses it exclusively (with LLVM backend)

Platform - IDE

Again, Microsoft drives it…

Visual Studio

  • used everywhere: PC, Xbox One, PS4
  • used with extensions:
    • various profilers & debuggers
    • help with code completion & formatting: Visual Assist X, Resharper

Others

  • SN Systems: proprietary EDG front end for Sony until PS4; extensions/toolchain
  • Metroworks CodeWarrior for Nintendo consoles
  • XCode - Just say No :)

Compilation

Compilation and linking are usually dreadfully slow

End result usually a single executable - size is ridiculous!

Optimizations are on by default, full debug builds have crawling FPS;
Various tricks:

  • #pragma optimize on/off "islands"
  • only specific modules are debug
  • mastery of reading optimized disassembly

Compilation (continued)

Some mitigation methods…

Unity builds

  • combine all/lots of source files into a couple of gigantic .cpp units
  • improves speeds due to way less churn on #include’s
    • basically poor man’s modules
  • can create hidden dependencies gotchas as opposed to normal pipeline
  • can hurt iteration (usual mitigation: extract out specific .cpp)

Various techniques

  • "include what you use" parser tools
  • template explicit instantiation & similar to reduce symbol count for linking

Distributed compilation

  • Use solution like FastBuild or Incredibuild to effectively create compilation farms

Fighting the compiler

Heed no warning!
Warnings are mopped under the floor - couple of favorite ones to disable…

  • signed/unsigned mismatch
  • conversion from T1 to T2 requires a narrowing conversion
  • conversion from T1 to T2, possible loss of data
  • conditional <expression> is constant
  • nonstandard extension used: nameless struct/union

Use the __force!
Eternal hope that magically sprinkling inline will make things faster…

inline, __inline, __forceinline
__attribute__((always_inline))
backgr

Coding styles & techniques

Flavors of C++

Traditionally was very C++98 but by now changed…

  • C++11: baseline
  • C++14: getting good traction
    • the major engines help with this - UE4 enables it by default
  • C++17: not yet, I predict some features will be embraced
    • if-with-initializer seems a favorite, guaranteed RVO, std::optional for errors etc

Due to differences in people’s experience, personality and time availability, adoption of the various new features and techniques is slow…

Personal way to help…

  • running a series of internal talks "C++11/14 for game dev"
  • newsletter about best practices and modern C++
  • promoting & sharing conference talks

Coding style

Every studio has a set of guidelines or a complete style guide.
Some of them recommend things that would really upset a C++ purist!

Example: Namespaces

  • not preferred (with exceptions: anonymous to force internal linkage)
  • Instead everything has a game specific prefix:
    • CShooterComponent, TShooterItem, EShooterState etc

Trivia

  • CamelCase rules the nation
  • K&R (or "Egyptian") style of braces very frowned upon - Allman is almost always used
  • auto destroys friendships

OOP is king

Preferred technique for game code - with some studios resisting!

Polymorphism

  • the preferred default technique
  • "What is a v-table?" - common interview question
  • lots of codebases have a Java-style Object ultimate base class

ECS

  • Entity-Component-Systems are prevalent in gameplay code
  • Everything hierachy of Entity, Node or Object's
  • Components do virtual Update, Tick, Draw or Render

Common communication methods

  • normally just tight coupling
  • delegate/event systems (heavily macro’ed for "usability"!)
  • typed/untyped message queues

Alternatives to OOP

Need for multithreading continuously growing…

  • I/O systems, loading & saving
  • Rendering, Animation, Navigation, etc decoupled from gameplay
  • Online sub-systems and services

New/old paradigms

  • Functional style
    • monad continuations - .Then(), .With() etc
    • seeking to minimize state, pursue purity
  • "Job-ifying"
    • Parallel Patterns Library (PPL) from Microsoft
    • Threading Building Blocks from Intel
    • Seldom the standard future and promise - usually every game engine has own equivalents

Templates

Traditionally, there was a tendency to downplay templates - changing now with modern standards and mature compilers

Normal usage

  • container work obviously
  • policy design: allocator, rendering, etc
  • variadic templates used to be emulated with "up to 11 arguments" horrible macros

Metaprogramming

  • seen as black magic and highly discouraged
  • due to project size - isolated islands where it thrives
  • sometimes custom reduced specific enable_if, void_t, traits etc
Poor man’s templates

Still a tendecy to use macros where template or constexpr functions would be more adequate

backgr

STL / Boost

STL

Adoption generally low…

  • console games seldom ship with STL containers
  • more usage in PC-only/indie
  • iostreams are the devil’s work!

Bespoke alternatives

  • specific allocation needs (and limited allocator model pre C++17)
  • associated (or perceived) bloat
  • slow or cumbersome debugging
  • not everyone is willing to follow STL coding style and naming

STL (continued)

std::string - best example…

  • every studio/engine reinvents the string wheel
  • specific localization needs - ties with game data
  • previous STL implementations made awkward choices (Ex: copy on write on older GCC)
  • no need for streams: C printf style preferred, I/O handled in bulk elsewhere

Bits & pieces

  • the Iterator concept is copied and reimplemented - if nothing else just to enable ranged-for’s
  • the STL atomics and locks are generally used as is
  • sparing use of algorithms, normally bespoke containers don’t play well with them

[EA]STL

EASTL from Electronic Arts - video game specific implementation of STL
Originally started 10 years ago for internal use, now open source (https://github.com/electronicarts/EASTL)

Normally follows the std:: nomenclature & style
Differences / Changes…

  • written in a more straightforward/direct way (less general)
    • easier to debug, faster release builds
  • simplified allocator model - games specific
    • alignment aware, naming support, etc
  • intrusive containers
  • fixed_ containers (no allocation, only within provided block)
  • new containers
    • ring_buffer, heap, priority_queue, etc
  • smart pointers, type traits - now obsolete

STL - SG14

Finally game dev is officially recognized in the ISO C++ Standard committee!

SG14 group
Video games and embedded programming study sub-group
Tries to propose new, optimized containers, data structures even language changes

Proposals & Papers in-flight

  • fixed point numeric library
  • ring buffer
  • intrusive containers
  • "in place" alternative to std::function
  • likely/unlikely optimization hints
  • bike shedding :)

Boost

Very frowned upon and highly discouraged…

asm

Boost (continued)

Reasons

  • clash of cultures:
    • Boost is "academic" and research driven
    • game dev is pragmatic and get-it-done
  • historically didn’t play well with MSVC
    • still doesn’t: boost::hana (but getting very close)
  • by now best libraries made it into the standard
  • difficulty to integrate & setup
    • bcp tool makes this easier
  • slow compilation times
backgr

Exceptions / RTTI / Reflection

Exceptions

Almost never used due to speed penalties of throw-ing and catch-ing

A small (not totally fair) demonstration…

#include <stdexcept>

int func()
{
    throw std::exception();
}

Compiled with /O2 optimizations on VS 2017
Let’s see disassembly: https://godbolt.org/g/wQXmTi

Exceptions (continued)

asm

Exceptions (continued)

asm

Exceptions - alternatives

Handling of errors…

  • during dev: hard exit is requested on error
  • C style last-error or status arguments
  • impossible to handle errors in constructors
    • solution is to have Create, Instantiate, Begin replacements
  • exceptions are still used sometimes in non critical code
    • online services
    • OS/system interactions
  • reputation problem feedback loop
    • past gen console platforms didn’t support them
    • compiler support was lackluster
    • dev didn’t use them

RTTI

Seldom used - normally turned off by default because it bloats the modules size

Very rare use of dynamic_cast - usually reimplemented manually via COM style interfaces

Reflection

A lot of games have involved reflection systems…

  • close live-link with editors and tools
    • values inspection, code hot reload
  • serialization for loading/saving; versioning
  • network replication, RPC’s
  • garbage collection

Custom solutions

  • preprocessor based decorations that both annotate code and generate registration calls
  • template metaprogramming for same purpose
  • mini IDL’s that generate additional cpp/h files
  • processing intermediate compiler data (ex: .PDB file)
  • actually modifiying the compiler, if access to it

Reflection - UE4

Example from Unreal Engine 4…

ue4 reflect

Reflection - UE4

Class member decorations…

ue4 reflect

Reflection - UE4

The ugly insides…

ue4 reflect

There is more…

  • Most used Patterns
    • Singleton - the anti-pattern of choice
    • Factory
    • Builder
    • Visitor (double-dispatch)
    • Policy based design
    • etc…
  • Lots and lots of preprocessor abuse
  • Whatever I missed from codebases I never worked on…

Closing

There you have it - a short survey of C++ in game development!

  • game dev pushes the bar due to video games hard requirements
  • for a time looked at as the ugly cousin in the basement of C++
  • coming back strong
    • better represented now in the C++ ecosystem

Attributions