A thread owns one seed
Start with 1,003 seeds so the count is deliberately not a multiple of a convenient workgroup width. Give each invocation one seed index and reject indices outside the valid count before reading or writing any buffer. The host validates the count against the allocation capacity and dispatch limits; the shader guard handles the rounded final workgroup. These two checks protect different boundaries. A shader guard cannot rescue a host that bound a smaller buffer than the advertised count.
Use a simple representation: position and velocity stored in explicit vec4 records or another documented layout. Keep padding and std430 rules aligned with the C++ serializer. Choose a supported local size from queried limits. Workgroup count is ceiling division, with overflow-safe host arithmetic and a cap on maxComputeWorkGroupCount. “My GPU is fast” is not a meaningful bound.
The first update can add a small deterministic drift, wrap positions inside a fixed box, and write a separate output buffer. There are no atomics or subgroup assumptions in this milestone, and no hardware ray-tracing extension is required. A tiny CPU oracle updates the same initial seeds so you can compare results before trusting the animation.
