Expand description
Per-vertex warp evaluation.
Each frame the warp mesh’s cols × rows vertices need their UVs warped
according to the preset’s per-vertex (Milkdrop “per_pixel”) equations and
the MilkDrop 2 zoom/rot/stretch/translate/warp formula.
§Hot path strategy
WarpExecutor precompiles each per-vertex equation into an
evalexpr::Node once at preset load and then reuses one scratch
MilkContext across all vertices of a frame. This replaces the previous
“clone evaluator state per vertex” approach, which allocated a fresh
HashMapContext (≈60 vars + math-function map) for every one of the
cols × rows vertices — 768 allocations per frame at the default 32×24
mesh, up to 18 432 at 192×96.
Per-vertex independence (each vertex sees the same per-frame state on
entry, regardless of what previous vertices wrote) is preserved by
snapshotting the motion outputs (zoom, zoomexp, rot, cx, cy,
dx, dy, sx, sy, warp) and the q1..q32 channels at the start
of the frame and restoring them before each vertex eval.
Structs§
- PerVertex
Motion 🔒 - Per-vertex motion outputs read from the evaluator after running per-vertex equations.
- Warp
Executor - Pre-compiled per-vertex equation executor.
Constants§
- PARALLEL_
EQ_ 🔒THRESHOLD - Minimum compiled-equation count before we hand the per-vertex loop to
rayon. Empirically: presets with ~3 cheap equations stay faster
sequential (warp-exec time is dominated by per-thread
MilkContextclone + work-stealing overhead at ~1 ms/frame baseline cost), while presets with 10+ equations see a 2-3× wall-clock win on a 12-thread box. Picked 8 as the breakpoint after measuring three reference presets (3 / 26 / 35 equations) on thebench_rendertool. - Q_
CHANNEL_ 🔒COUNT - Number of
q*channels we snapshot/restore between vertices. MilkDrop 2 exposesq1..q32; the underlyingMilkContextreserves 64 slots but only the first 32 are user-facing.
Functions§
- read_
motion 🔒 - read_
q_ 🔒snapshot - warp_
uv_ 🔒md2 - MilkDrop 2 warp UV formula.
- write_
motion 🔒 - write_
q_ 🔒snapshot