Machinery Game Engine Notes
Created on 2023-03-14T07:21:03-05:00
- Engine is based entirely on plugins; so engine is basically a host that loads plugins to do everything the game needs.
- "Creation Graph" is a node based system to load/generate/modify content on its way to be rendered.
- Materials/textures seem to be associated with a graph or a prototype graph. This graph then determines how those media files are transformed (kinda like pipelines in XNA/monogame.) So a compression node in the graph will compress textures with some outside tool.
- Materials and textures come out of a creation graph. The output node of the graph determines what kind of creation graph it is.
- Nodes handle loading images from files, setting filter and mipmapping details, possibly compressing the image.
- Editor had live collaboration support with multiple developers
- Supported hot code reloading
- Probably made easier by using the plugin framework; each plugin as a DLL, just load it, easy to reload that way.
- Central data model
- Sounds a bit like GSL/RDF graph shenanigans. Define data blocks as RDF and central tooling parses those graphs to create serialization/editor/synchronization etc boilerplates.
- Was called "The Truth."
- Data model uses write/commit semantics. "begin write" creates a copy to be modified, commit does an atomic pointer switch. Commit can also place the old value in to an undo scope. Undo-redo then just performs the atomic swap back to the original version that was cloned.
- Puzzle here is how data is managed in such a way that the atomic swaps were possible.
- UI is accumulated in to one model (batched) and sent as a single draw call. Clipping rectangles are also sent to the shader to be processed on the GPU.
- Overlays are put in a dedicated index buffer, combined before draw, and stuffed on top of everything before submission.
- Immediate mode UI; controls don't "exist" but have unique IDs set while drawing. ID is used to determine how to react to events (ex. if IDs change between renders, generate mouse exit events.)
- https://www.youtube.com/watch?v=mUJyms9WstQ
- https://www.youtube.com/watch?v=U_8utTBfE-U
- https://www.youtube.com/watch?v=yYq_dviv1B0
- https://web.archive.org/web/20220316014137/https://ourmachinery.com/post/multi-threading-the-truth/
- Datums have an ID which is an index in to a lookup table with the value pointers.
- Updating an object is an atomic swap of the pointer in this lookup table.
- A cross-object transactional system could be done by replacing the root pointers.
- But this is very complicated and requires copies of trees and so forth. So they end up not doing it.
- Heirarchial storage
- Block of 1024 objects, superblock of 1024 blocks, root of 1024 superblocks.
- Lazily allocates block/superblock as-needed; ensures old values don't get invalidated during an allocation phase.
- One suggestion was to have each thread locked to a given superblock so its own datums don't fight for ID allocation with others. This technically works but limits your thread count to the number of superblocks.
- Garbage collection
- Can't delete old datums until they aren't in use
- Partly relies on a semaphore at end of frame; at this point all overwritten things are seen as implicitly done being read.
- But stuff in undo stacks can't be reapt
- Threads that take more than a frame have to do something like reference counting or [[Hazard Pointers]].
- https://web.archive.org/web/20210829092854/https://ourmachinery.com/post/little-machines-working-together-part-1/
- Plugins use a struct of function pointers as a kind of interface.
- Plugins are managed through `load_...` and `unload_...` commands opened with dlsym.
- `reload` parameter is given to load and unload to notify when the module is being yeeted.
- `...` is name of plugin such as `load_vorbis` and is apparently chosen so plugins could be statically linked.
- Using size of struct as a versioning mechanism, the "microsoft approach."
- Using pointers to structs to avoid using versioning; since fields added later do not invalidate pointers to earlier members.
- Also some kind of plugin registry to track names, DLLs, and the dependencies of those individual plugins.