Skip to main content

Module soa

Module soa 

Source
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§

FieldSoaColumn
A field-split component column: one contiguous Vec<f32> per component field.

Traits§

SoaLayout
Per-type knowledge the generic FieldSoaColumn needs to scatter a component into its f32 field arrays and gather it back.