Kirill Shabordin, CTO, Social Quantum
Is Lua a panacea or a dead end? Is OOP necessary for gamedev? How many Lua scripters does it take to change a light bulb?
6. • Standart Binders
• The Book (unit tests)
• Reference LuaC
• Bytecode
• Spirit of Lua (WHAT???)
• No Limits
Holy Cows
7. • Engine — monarchy; GET style
• Script — anarchy; CREATE style
• Hybrid — democracy; KILL’EM ALL style
Who Owns the World?
8. • Object ownership is for engine
• Classic “get/set” stateful API
• No direct created objects
• Creation tool is required
• Lua is “config with functions”
• Often user can’t enhance engine API
An Engine As King of the Hill
9. • Object ownership is for script
• Direct created objects
• Object’s lifecycle controlled by script
• Often has an OOP architecture
• Creation tool is NOT required
• User can enhance API by Lua
A Script is the Staff of Life
10. • Object ownership is smart
• Creating objects from any worlds
• Object’s lifecycle controlled by WHAT?
• Creation tool is NOT required
• User can write Lua as well as C++ code
• Often have one API for C++ and Lua users
Between Two Evils ’tis Not Worth
Choosing
11. Each GameObject has a script
Classic game loop out of user code
Ghost entry point
You need event system for linking scripts
OR
Application has a script and a GO graph
Obvious entry point
Traditional architecture of game loop
Event systems / FSM states etc… for application flow
Bark Up the Wrong Tree
12. There aren't problems in C++
Nor there are problems in Lua
Problems are in crossroad
Milestone Two
13. • local val = 42
• local val = true
• local val = ‘Ololo’
• local val = {…}
• local val = function() … end
• local val = myApiClass.new(…) root of all evil
Roots
14. • LuaC has C bridge, NOT C++
• LuaC uses userdata and metatables as tools
• LuaJIT also uses FFI lib (for pure C, sure)
Between Two Worlds
16. You have three ways:
1. Write a better Lua code (mua-ha-ha-ha)
2. Investigate bottlenecks and fix them
3. Change the nature of Lua
4. Or do nothing
Milestone Three
17. • Create C methods for calling class methods
Include something inheritance implementation
• Create Lua metatable for caller and gc
• Compile it
Prepare myClass
18. Val = MyEngine.Class.new(param)
• Create userdata for MyEngine.Class
• Create MyEngine.Class instance on heap
• call constructor for C++ class MyEngine::Class with param
• save pointer (or shared pointer, or copy….) to userdata
• set metatable (static for every type) for method caller, gc, etc
• Create or set ref Val to this userdata
Cost of Creating Object
19. Res = (A + B - C) * D
What’s Wrong in This Code?
20. Res = (A + B - C) * D
• Res = mul(sub(add(A, B), C), D)
• Res = D.__mul(B.__sub(A.__add(A, B), C), D)
• Tmp1 = A._add(A, B) ‘internal’ assign
• Tmp2 = B._sub(B, Tmp1) ‘internal’ assign
• Res = D_mul(Tmp2, D) ‘external’ assign
Look Inside
21. • Don’t use metamethods = don’t return values
• Use “CryE”-like ugly calls : SumVectors( a, b, res)
• Implement all the necessary operations in C++
Solution#1 — No woman no cry
22. • Stack record is Variant
• Variant size is eq to the max type size
• Ex: vec3 increases the stack size by about 3 times
• Pros — speed, cons — size
• Ownership: no GC for stack values in Lua
Solution#2 — More POD Types
23. • Add __assign metamethod a = b -> a.__assign(b)
• Create caches for each necessary type
Solution#3 — Cache It
Type cacher
Global Binder Userdata cache
Heap type T cache [maxN]
24. • All userdata for binding of the same size
• Assign — point for drop temporary cache
• Cache created for each necessary type
• Garbage Collector isn’t used in cache
• Cache overload produce normal objects
• Special allocators used for optimisation
How It Works
25. New Age Fusion
CODE AST LUAC
BYTECODE
LuaC, have eval
CODE AST IR
BYTECODE
JIT Ideas, have eval
EXECUTE
PREPARE HW
BYTECODE
EXECUTE
CODE AST LLVM IR
External LLDB, eval is restricted
LLVM
OPTIMIZATIONS
LUAC
BYTECODE
EXECUTE
26. LuaC and LuaJIT are more than enough for any
practical issue
… in case you write clean and smart code
Milestone Four