Skip to main content

Module gpu_layout

Module gpu_layout 

Source
Expand description

GPU-compute force-directed layout — the elite engine’s must-land core.

A wgpu compute-shader n-body layout: per-node weights + CSR adjacency are streamed from an Arrow edge batch straight into GPU storage buffers, and the node positions then iterate in VRAM (ping-pong srcdst, no readback per step) until they settle. The host reads the converged positions back as plain [f32; 2] DATA — exactly the contract a headless test asserts on.

This is the answer to the layout-perf-at-scale curse: the all-pairs repulsion is the same O(n²) compute pattern as the boids in [facett_core::render::gpu::particles] (reused verbatim — storage ping-pong, a @workgroup_size(64) kernel, the headless request_adapter device probe), so a 10k–100k-node re-layout runs in real time on the GPU instead of the CPU.

§Force model (Fruchterman-Reingold, velocity-integrated)

For node i with mass wᵢ (its streamed weight):

  • repulsion from every other node j: a Fruchterman-Reingold k/d push, rep · wᵢ · wⱼ · (pᵢ − pⱼ) / dist² — the (pᵢ−pⱼ) numerator carries one dist, so the magnitude is rep·wᵢ·wⱼ / dist (heavier nodes shove harder → important nodes claim space),
  • attraction along each CSR neighbour t: a Hooke spring attr · (dist − ideal) · (pₜ − pᵢ)/dist (pulls connected nodes to ideal_len),
  • gravity −grav · pᵢ keeps the component centred,
  • integrate v ← (v + F/wᵢ·dt)·damp, p ← p + v·dt (heavy nodes move slower).

It is a pure, deterministic function of the seed + params + step count (FC-7): no RNG (the seed is a golden-angle spiral), fixed loop order. The CPU step_cpu is the no-GPU fallback and the parity reference the GPU readback proof checks against — the WGSL cs_layout mirrors it line-for-line.

§Roadmap (see .nornir/elite-graph-engine.md)

The O(n²) repulsion is the foundation; a GPU Barnes-Hut quadtree (or a Morton / grid binning) drops it to O(n log n) for the 100k case — documented there, not built here, because the foundation must land + test clean first.

Structs§

GraphCsr
CSR (compressed-sparse-row) adjacency + per-node weight — the GPU-streamable graph. offsets[i]..offsets[i+1] indexes into targets for node i’s neighbours; weights[i] is node i’s mass. The three Vecs map 1:1 onto the three GPU storage buffers (offsets/targets read-only, weights packed into the node buffer), so this is the upload format — no repack at the seam.
LayoutParams
Force-layout tuning. Default is a calm, convergent spring system.
LayoutState
The mutable layout state: one position + velocity per node (the ping-pong the GPU iterates in VRAM; here, the CPU mirror). Positions are the DATA a test reads.

Functions§

relax_cpu
Run the CPU fallback to convergence: seed, then iters step_cpus. Returns the settled state (positions = DATA). Deterministic in (g, p, iters).
step_cpu
One CPU force step — the no-GPU fallback and the parity reference the WGSL cs_layout mirrors exactly. Pure: step_cpu(s) depends only on s, g, p.