Expand description
Field-split (Structure-of-Arrays) component storage — the physical layout the AGDF compute kernels want.
A normal CRPECS column is Vec<T> (Array-of-Structures within the
component): one struct after another. For a compute-heavy hot loop that
sweeps a few fields over many entities, that wastes the CPU’s SIMD slots and
cache. A FieldSoaColumn instead stores one contiguous f32 array per
field, so each field streams without gather and tiles cleanly into
f32x8 (the resident layout the bench showed reaches ~4×).
This is the data-layer realisation of “adapt the HOW, not the WHAT”: the
component’s semantics are unchanged, only its column’s physical mapping.
It is opt-in per component (#[component(layout = "soa")]) and lives
behind the same Box<dyn AnyVec> as any column, so the rest of CRPECS —
pages, domains, queries on other components, serialization — is untouched.
A field-SoA component can’t yield &T (its bytes aren’t a contiguous T),
so it is read by value via the Soa<T> query / World::clone_component, or
in bulk via the per-field arrays for SIMD.
The generic column needs only a tiny amount of per-type knowledge — how to
scatter a value into the field arrays and gather it back — supplied by
SoaLayout, which #[derive(Component)] generates for layout = "soa"
structs whose fields are all f32.
(Note: “field array” here is the per-component-field Vec<f32>; it is
unrelated to the engine’s Lane negotiation concept.)
Structs§
- Field
SoaColumn - A field-split component column: one contiguous
Vec<f32>per component field.
Traits§
- SoaLayout
- Per-type knowledge the generic
FieldSoaColumnneeds to scatter a component into itsf32field arrays and gather it back.