Generational handle pool + slab allocator. Layer 1 — depended on by every other module that owns objects with stable identity.
Pointers go stale when a backing array reallocates, and they make
serialization, debugging, and cross-thread ownership painful. Mjolnir
addresses pooled objects through Handle{index, generation}.
Freed slots bump their generation, so a stale handle resolves to “not
found” rather than a use-after-free.
A distinct Handle per pool type
(NodeHandle, MeshHandle, …) keeps the safety
at compile time without changing the layout.
Backing array + a free-list of recycled indices. alloc
reuses the oldest freed slot before growing. free flips
active and bumps generation (skipping zero on
wrap; zero is the invalid-handle sentinel).
Range allocator over a single flat buffer, partitioned into a handful
of size classes. Used by gpu.MeshManager to sub-allocate
vertex / index / skinning ranges out of a couple of giant GPU buffers —
keeps allocation O(1), avoids per-mesh vk.Buffer objects,
and gives GPU draw indirect a stable base offset.