dynamis-world 0.6.0

GPU-driven physics engine
Documentation
use super::FrameParams;
use super::dispatch::{CONTACT_BEGIN, CONTACT_RELAY, ISLAND_LINK_CONTACTS};
use super::stage::{CONTACT, CORE, RO, RW, Stage, UNIFORM, whole};
use crate::dynamics::buffers::WorldBuffers;
use dynamis_gpu::{ComputeRecorder, GpuContext};
use dynamis_layout::{
    COUNTER_ARCHIVED, COUNTER_CONTACTS, COUNTER_EVENTS, COUNTER_RESTING_INDEX,
    COUNTER_SPILLOVER_EVENTS,
};

pub(super) struct Islands {
    contact_relay: Stage,
    contact_begin: Stage,
    island_init: Stage,
    island_link_contacts: Stage,
    island_link_constraints: Stage,
    island_jump: Stage,
}

impl Islands {
    pub(super) fn build(context: &GpuContext, buffers: &WorldBuffers, per_row: u32) -> Self {
        Self {
            contact_relay: Stage::build(
                context,
                "contact_relay",
                include_str!("shaders/contact_relay.wgsl"),
                per_row,
                CONTACT,
                &[
                    (RO, whole(&buffers.contacts.archive)),
                    (RW, buffers.counter(COUNTER_ARCHIVED)),
                    (RW, whole(&buffers.contacts.manifolds)),
                    (RW, buffers.counter(COUNTER_CONTACTS)),
                    (RW, whole(&buffers.contacts.contact_matched)),
                    (RW, whole(&buffers.events)),
                    (RW, buffers.counter(COUNTER_EVENTS)),
                    (RW, buffers.counter(COUNTER_SPILLOVER_EVENTS)),
                    (UNIFORM, whole(&buffers.params)),
                    (RO, whole(&buffers.bodies.rows)),
                    (RO, whole(&buffers.bodies.states)),
                    (RO, whole(&buffers.bodies.descriptors)),
                ],
                &[],
            ),
            contact_begin: Stage::build(
                context,
                "contact_begin",
                include_str!("shaders/contact_begin.wgsl"),
                per_row,
                CONTACT,
                &[
                    (RW, whole(&buffers.contacts.manifolds)),
                    (RW, buffers.counter(COUNTER_CONTACTS)),
                    (RO, whole(&buffers.contacts.contact_matched)),
                    (RW, whole(&buffers.events)),
                    (RW, buffers.counter(COUNTER_EVENTS)),
                    (RW, buffers.counter(COUNTER_SPILLOVER_EVENTS)),
                    (UNIFORM, whole(&buffers.params)),
                    (RO, whole(&buffers.contacts.resting)),
                    (RO, whole(&buffers.contacts.resting_live)),
                    (RO, whole(&buffers.contacts.resting_index.major)),
                    (RO, whole(&buffers.contacts.resting_index.minor)),
                    (RO, whole(&buffers.contacts.resting_index.payload)),
                    (RW, buffers.counter(COUNTER_RESTING_INDEX)),
                ],
                &[],
            ),
            island_init: Stage::build(
                context,
                "island_init",
                include_str!("shaders/island_init.wgsl"),
                per_row,
                CORE,
                &[
                    (UNIFORM, whole(&buffers.params)),
                    (RW, whole(&buffers.islands.parents)),
                    (RW, whole(&buffers.islands.state)),
                ],
                &[],
            ),
            island_link_contacts: Stage::build(
                context,
                "island_link_contacts",
                include_str!("shaders/island_link_contacts.wgsl"),
                per_row,
                CORE,
                &[
                    (RO, whole(&buffers.bodies.states)),
                    (RO, whole(&buffers.bodies.descriptors)),
                    (RO, whole(&buffers.contacts.manifolds)),
                    (RW, buffers.counter(COUNTER_CONTACTS)),
                    (RW, whole(&buffers.islands.parents)),
                    (RW, whole(&buffers.islands.wake_flags)),
                ],
                &[],
            ),
            island_link_constraints: Stage::build(
                context,
                "island_link_constraints",
                include_str!("shaders/island_link_constraints.wgsl"),
                per_row,
                CORE,
                &[
                    (UNIFORM, whole(&buffers.params)),
                    (RO, whole(&buffers.bodies.states)),
                    (RO, whole(&buffers.bodies.descriptors)),
                    (RO, whole(&buffers.constraints.descriptors)),
                    (RO, whole(&buffers.constraints.runtime)),
                    (RW, whole(&buffers.islands.parents)),
                    (RW, whole(&buffers.islands.wake_flags)),
                ],
                &[],
            ),
            island_jump: Stage::build(
                context,
                "island_jump",
                include_str!("shaders/island_jump.wgsl"),
                per_row,
                CORE,
                &[
                    (UNIFORM, whole(&buffers.params)),
                    (RW, whole(&buffers.islands.parents)),
                ],
                &[],
            ),
        }
    }

    pub(super) fn record(
        &self,
        recorder: &mut ComputeRecorder,
        buffers: &WorldBuffers,
        params: &FrameParams,
    ) {
        let constraint_active = params.constraint_count > 0;

        self.contact_relay
            .record_indirect(recorder, &buffers.dispatch, CONTACT_RELAY);
        self.contact_begin
            .record_indirect(recorder, &buffers.dispatch, CONTACT_BEGIN);
        self.island_init.record(recorder, params.dynamic_count);
        self.island_link_contacts.record_indirect(
            recorder,
            &buffers.dispatch,
            ISLAND_LINK_CONTACTS,
        );
        if constraint_active {
            self.island_link_constraints
                .record(recorder, params.constraint_count);
        }
        for _ in 0..params.island_rounds {
            self.island_jump.record(recorder, params.dynamic_count);
        }
    }
}