Documentation
    Preparing search index...

    Interface ParticleGpuSimulation

    The GPU integration driver a simulation: "gpu" emitter steps through (§36 "GPU compute simulation"; §82; gap row R-31).

    A compute-capable backend mints one — @fourjs/render-webgpu's WebgpuRenderer.createParticleSimulation({ systemId, capacity }) is the implementor today — and the application binds it with emitter.bindGpuSimulation(...). The interface is structural, like ParticleForceField and @fourjs/render's ParticleDrawable, because the frozen §3.1 matrix gives this package core, math, scene and nothing render-shaped: the two declarations are pinned against each other by tests on both sides, never by the compiler.

    CPU spawn + GPU integrate. Every §33-bearing decision stays on the CPU — the seeded RNG stream and its pinned four-draws-per-spawn order, burst scheduling, the emission accumulator, capacity accounting, ageing and expiry, and the §36 ramps (functions of age, which never leaves the CPU). The device takes exactly the O(n)-arithmetic half: one semi-implicit Euler step per particle per fixed step, under constant gravity. That split is what keeps a GPU emitter's spawn stream bit-identical to a CPU emitter's with the same seed — pinned by test — while the integrated state lives where the work is.

    A GPU-simulated system's positions and velocities live on the device. They sit outside every §33 tier this engine claims: the kernel's arithmetic order is fixed, but WebGPU promises no cross-adapter float reproducibility, and device f32 arithmetic differs from the CPU integrator's binary64 intermediates by rounding — so GPU simulation is display-tier motion. No §33 golden may checksum a GPU pool, and none does. §34 follows: there is no particle snapshot surface today, this packet deliberately adds none for GPU emitters — a CPU-side snapshot would capture spawn-stale lanes and restoring it would be a lie — and a readback-based snapshot is its own future packet with its own determinism argument (the GPU-readback RFC the R-1 plan names). reset() stays valid: an empty pool needs no device state.

    Per step(dt, time), in order: one ParticleGpuSimulation.integrate over the pre-expiry live count (skipped when that count or the delta is zero — both are identity steps), then zero or more ParticleGpuSimulation.moveSlot calls mirroring the pool's swap-remove compaction exactly (never with from === to), then one ParticleGpuSimulation.writeSpawn per successfully spawned particle. All indices are pool slots in [0, capacity).

    interface ParticleGpuSimulation {
        capacity: number;
        isParticleGpuSimulation: true;
        integrate(
            count: number,
            deltaSeconds: number,
            gravityX: number,
            gravityY: number,
            gravityZ: number,
            extras?: ParticleGpuIntegrateExtras,
        ): void;
        moveSlot(from: number, to: number): void;
        writeSpawn(
            index: number,
            positionX: number,
            positionY: number,
            positionZ: number,
            velocityX: number,
            velocityY: number,
            velocityZ: number,
        ): void;
    }
    Index
    capacity: number

    Slots the device buffers were allocated for. Must equal the emitter's pool capacity; bindGpuSimulation refuses a mismatch.

    isParticleGpuSimulation: true

    The brand, a literal true — the isParticleDrawable technique, so the cross-package check is one property load.

    • Integrates the first count slots by deltaSeconds under constant gravity — v += g·dt, then p += v·dt, the emitter's documented closed form. Never called with count === 0.

      Parameters

      Returns void

    • Copies slot from's position and velocity over slot to — the device mirror of ParticlePool.kill's swap-remove (from is the last live slot, to the expired one; from's old contents become dead). Called in exactly the CPU compaction order, never with from === to.

      Parameters

      • from: number
      • to: number

      Returns void

    • Writes a freshly spawned particle's position and velocity into slot index — the CPU-owned spawn state entering device residency.

      Parameters

      • index: number
      • positionX: number
      • positionY: number
      • positionZ: number
      • velocityX: number
      • velocityY: number
      • velocityZ: number

      Returns void