Skip to content

Multibody contact/joint solve produces zero impulses on macOS (naga MSL loop miscompile) #5

Description

@haixuanTao

On macOS (wgpu/Metal), the rbd multibody solver's contact and PD-joint sweeps have no effect: bodies free-fall through the ground, and more solver iterations make the blow-up worse (gravity integrates per TGS iteration while constraints contribute nothing).

Root cause is not in nexus — it's a naga 29 MSL backend bug: the writer renders a loop's continuing block at the top of the next while iteration and re-evaluates the break_if condition there, after the continuing statements have advanced the loop variables the condition reads. rust-gpu while loops (conditional backedge computed in the loop body) therefore exit one body-execution early on Metal. In solve_contact_constraints_par, the per-lane while i < ndofs { …; i += LANES } reductions have exactly one iteration per lane — so they execute zero times, J·v evaluates to 0, and every impulse stays 0. CUDA and Vulkan (spirv-passthrough) are unaffected, which makes it look like a nexus solver bug when it isn't.

Fix is upstream: gfx-rs/wgpu#9815 (fixes the long-open gfx-rs/wgpu#4558). Until it ships in a wgpu release, a vendored-naga [patch.crates-io] with the condition-snapshot fix restores correct Metal behavior — verified against a CUDA golden reference of the same SPIR-V (step-0 contact impulse matches to 4 decimals; an RL training run over the engine converges identically on macOS and CUDA after the patch).

Happy to share the diagnosis trail (deterministic-seed intermediate diffing down to an in-kernel lane-liveness probe) or the vendored patch. (Originally filed on the old repo as dimforge/nexus-rustgpu#3 before noticing development moved here.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions