Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-graphview/.nornir/design.md

facett-graphview — design note (foundation spike)

A domain-agnostic, scalable 2D graph render engine, vello-backed, that runtime-selects its backend by hardware: vello (GPU/wgpu compute) when a usable GPU exists, vello_cpu (multithreaded SIMD) as the no-GPU fallback. The eventual single home for every graph surface — nornir's arch/dep/release dashboards, korp, graph-DB browsing — aiming to beat Graphviz on interactivity

This is task #17's FOUNDATION: it proves the architecture, the runtime backend select, the CPU raster path, the egui-embeddable frame, and carries the benchmark evidence. It deliberately STUBS the heavy engine pieces (LOD, clustering, bundling, streaming layout, adapters) behind documented seams.

What landed (proven)

Versions (the key compatibility result)

crate version note
egui/eframe 0.34 the facett workspace pin
wgpu 29.0.3 what egui-wgpu 0.34 pins
vello 0.9.0 depends on wgpu 29.0.3 — exactly the egui stack's wgpu
vello_cpu 0.0.6 already a transitive dep of epaint 0.34 (egui's paint)
vello_common 0.0.6 with vello_cpu

Two findings made integration painless:

  1. vello_cpu 0.0.6 was already in the workspace lock — epaint 0.34 pulls it in. The CPU path was guaranteed to build before a line was written.
  2. vello 0.9 pins wgpu 29.0.3, the same wgpu egui-wgpu 0.34 uses. The GPU path will coexist with eframe inside a facett host with no version war.

vello_cpu 0.0.6 is young; its API matched: RenderContext::new(u16,u16), set_paint(impl Into<PaintType>), set_stroke(Stroke), fill_path/stroke_path /fill_rect, flush(), render_to_pixmap(&mut Pixmap); Pixmap::take_unpremultiplied() for PNG. kurbo/peniko/color are re-exported.

Benchmark — vello_cpu raster vs epaint tessellation

cargo bench -p facett-graphview (benches/raster.rs), 1600×1000 frame:

graph vello_cpu raster epaint tessellate
~1k edges (480 nodes) ~23 ms ~1.5 ms
~10k edges (5k nodes) ~112 ms ~11 ms

Read this honestly. It is NOT apples-to-apples and it does NOT say "vello_cpu beats epaint" on the CPU:

So on the CPU, full software raster is naturally heavier than mesh-building. The real "is it worth it" win is the GPU path: vello on wgpu rasterizes on the GPU where fill cost is ~free and the compute pipeline scales to scenes that choke epaint's CPU tessellator (which is O(primitives) on the main thread every frame and has no culling/LOD). That is the architecture this spike puts in place. The CPU number is the floor (the no-GPU fallback), and ~112 ms for a 10k-edge full-canvas raster with zero LOD/culling is already a usable floor — the stubs below cut it hard.

GRAPH-CLIP-TEST (landed) — the start→pixel clip discipline

The graph twin of facett-map3d's clip pipeline now ships in src/clip.rs (render_graph_clipped + the gpu lane render_graph_clipped_gpu + pick). It renders a GraphModel into a widget rect ⊆ canvas, instruments the chain layout → cull → nodes → edges → picking → composite, and proves nothing is painted outside the rect (composite.ink_outside_rect == 0) with a final-picture PNG blob a test reads back + a deliberately-unclipped bug variant that goes RED (sensitivity). Full note: .nornir/graph-clip-test.md. Tests: tests/graph_clip.rs (CPU + gpu).

What is STUBBED (documented, not built)

Each has a clear seam + TODO in code:

Path from this spike to the full engine (#17) + adapters (#22)

  1. Land viewport-culling + LOD in cpu.rs (biggest floor win; cheap).
  2. Wire the live GPU path: gpu::GpuRenderer (device/queue/vello renderer/ target) + readback, then the egui_wgpu paint callback for in-app embedding. Add a real gpu::probe_usable_gpu-driven decide at host start-up.
  3. Add text glyphs (labels + badges) — shared font handle.
  4. Add the optional layout service + clustering/bundling as the engine grows toward Graphviz-scale interactivity.
  5. Write the adapters (#22) in the consuming crates (nornir dep/arch/release, korp, FalkorDB, pipeline) as -> GraphModel converters; swap nornir's draw_graph painter for facett_graphview::render_to_rgba behind its egui UI.