dynamis-rigid 0.7.0

Rigid body integration, islands, CCD, and constraint solving
Documentation
use super::streams::RigidStream;
use super::{CONTACT, IDENTITY};
use crate::RigidFrame;
use crate::sort;
use dynamis_abi::Count;
use dynamis_abi::{
    COUNTER_ARCHIVED, COUNTER_BREAKS, COUNTER_CONTACTS, COUNTER_EVENTS, COUNTER_RESTING,
    COUNTER_RESTING_GATHER, COUNTER_RESTING_INDEX, COUNTER_RESTING_PENDING, COUNTER_SLEPT,
    COUNTER_SPILLOVER_EVENTS, COUNTER_SPILLOVER_RESTING, COUNTER_WOKE_DEFERRED,
};
use dynamis_broadphase::BroadphaseStream;
use dynamis_gpu::Resources;
use dynamis_gpu::{ComputeRecorder, GpuContext};
use dynamis_pass::Stage;
use dynamis_shader::{CORE, GEOMETRY_INDEX, JOINTS, rows, stream, workgroups};
use dynamis_sort::RadixSort;
use dynamis_state::StateStream;

pub struct Commit {
    thaw_contacts: Stage,
    freeze_contacts: Stage,
    resting_gather: Stage,
    resting_commit: Stage,
    contact_archive: Stage,
    constraint_breaks: Stage,
    joint_states: Stage,
    archive_count_sync: Stage,
    static_wake_clear: Stage,
    query: Stage,
    observe: Stage,
}

impl Commit {
    pub fn build(context: &GpuContext, streams: &impl Resources) -> Self {
        Self {
            thaw_contacts: Stage::build(
                context,
                "thaw_contacts",
                stream(
                    context,
                    include_str!("../shaders/thaw_contacts.wgsl"),
                    CONTACT,
                    "work",
                    RigidStream::RestingContacts,
                ),
                streams,
                &[
                    ("resting", RigidStream::RestingContacts.whole()),
                    ("resting_live", RigidStream::RestingLive.whole()),
                    ("resting_next", RigidStream::RestingNext.whole()),
                    ("resting_free", RigidStream::RestingFree.whole()),
                    ("resting_count", dynamis_state::counter(COUNTER_RESTING)),
                    ("body_states", StateStream::BodyStates.whole()),
                    ("row_of_body", StateStream::BodyRowOfId.whole()),
                    ("body_activity", RigidStream::BodyActivity.whole()),
                    ("contacts", RigidStream::Contacts.whole()),
                    ("contact_count", dynamis_state::counter(COUNTER_CONTACTS)),
                    ("events", RigidStream::Events.whole()),
                    ("event_count", dynamis_state::counter(COUNTER_EVENTS)),
                    (
                        "spillover",
                        dynamis_state::counter(COUNTER_SPILLOVER_EVENTS),
                    ),
                    ("params", StateStream::Params.whole()),
                ],
                &[],
            ),
            resting_gather: Stage::build(
                context,
                "resting_gather",
                stream(
                    context,
                    include_str!("../shaders/resting_gather.wgsl"),
                    IDENTITY,
                    "work",
                    RigidStream::RestingContacts,
                ),
                streams,
                &[
                    ("resting", RigidStream::RestingContacts.whole()),
                    ("resting_count", dynamis_state::counter(COUNTER_RESTING)),
                    ("resting_live", RigidStream::RestingLive.whole()),
                    ("index_major", RigidStream::RestingIndexMajor.whole()),
                    ("index_minor", RigidStream::RestingIndexMinor.whole()),
                    ("index_slots", RigidStream::RestingIndexSlots.whole()),
                    ("gathered", dynamis_state::counter(COUNTER_RESTING_GATHER)),
                ],
                &[],
            ),
            resting_commit: Stage::build(
                context,
                "resting_commit",
                workgroups(
                    context,
                    include_str!("../shaders/resting_commit.wgsl"),
                    CORE,
                ),
                streams,
                &[
                    ("slept", dynamis_state::counter(COUNTER_SLEPT)),
                    ("gathered", dynamis_state::counter(COUNTER_RESTING_GATHER)),
                    ("index_count", dynamis_state::counter(COUNTER_RESTING_INDEX)),
                    (
                        "deferred_woke",
                        dynamis_state::counter(COUNTER_WOKE_DEFERRED),
                    ),
                    ("pending", dynamis_state::counter(COUNTER_RESTING_PENDING)),
                ],
                &[],
            ),
            freeze_contacts: Stage::build(
                context,
                "freeze_contacts",
                stream(
                    context,
                    include_str!("../shaders/freeze_contacts.wgsl"),
                    CORE,
                    "work",
                    RigidStream::Contacts,
                ),
                streams,
                &[
                    ("contacts", RigidStream::Contacts.whole()),
                    ("contact_count", dynamis_state::counter(COUNTER_CONTACTS)),
                    ("body_states", StateStream::BodyStates.whole()),
                    ("resting", RigidStream::RestingContacts.whole()),
                    ("resting_live", RigidStream::RestingLive.whole()),
                    ("resting_count", dynamis_state::counter(COUNTER_RESTING)),
                    (
                        "spillover",
                        dynamis_state::counter(COUNTER_SPILLOVER_RESTING),
                    ),
                    ("body_descs", StateStream::BodyDescriptors.whole()),
                    ("resting_next", RigidStream::RestingNext.whole()),
                    ("resting_free", RigidStream::RestingFree.whole()),
                    ("collider_owners", StateStream::ColliderOwners.whole()),
                ],
                &[],
            ),
            contact_archive: Stage::build(
                context,
                "contact_archive",
                stream(
                    context,
                    include_str!("../shaders/contact_archive.wgsl"),
                    CORE,
                    "work",
                    RigidStream::Contacts,
                ),
                streams,
                &[
                    ("contacts", RigidStream::Contacts.whole()),
                    ("archive", RigidStream::ContactArchive.whole()),
                    ("contact_count", dynamis_state::counter(COUNTER_CONTACTS)),
                ],
                &[],
            ),
            constraint_breaks: Stage::build(
                context,
                "constraint_breaks",
                rows(
                    context,
                    include_str!("../shaders/constraint_breaks.wgsl"),
                    CORE,
                    Count::Constraints.field(),
                ),
                streams,
                &[
                    ("params", StateStream::Params.whole()),
                    ("constraint_runtime", StateStream::ConstraintRuntime.whole()),
                    ("constraint_breaks", StateStream::ConstraintBreaks.whole()),
                    ("break_count", dynamis_state::counter(COUNTER_BREAKS)),
                ],
                &[],
            ),
            joint_states: Stage::build(
                context,
                "joint_states",
                rows(
                    context,
                    include_str!("../shaders/joint_states.wgsl"),
                    JOINTS,
                    Count::Constraints.field(),
                ),
                streams,
                &[
                    ("params", StateStream::Params.whole()),
                    ("body_states", StateStream::BodyStates.whole()),
                    ("body_descs", StateStream::BodyDescriptors.whole()),
                    (
                        "constraint_descs",
                        StateStream::ConstraintDescriptors.whole(),
                    ),
                    ("constraint_rows", RigidStream::ConstraintRows.whole()),
                    ("constraint_runtime", StateStream::ConstraintRuntime.whole()),
                    ("joint_states", RigidStream::JointStates.whole()),
                ],
                &[],
            ),
            archive_count_sync: Stage::build(
                context,
                "archive_count_sync",
                workgroups(
                    context,
                    include_str!("../shaders/archive_count_sync.wgsl"),
                    CORE,
                ),
                streams,
                &[
                    ("contact_count", dynamis_state::counter(COUNTER_CONTACTS)),
                    ("archive_count", dynamis_state::counter(COUNTER_ARCHIVED)),
                    ("contacts", RigidStream::Contacts.whole()),
                ],
                &[],
            ),
            static_wake_clear: Stage::build(
                context,
                "static_wake_clear",
                rows(
                    context,
                    include_str!("../shaders/static_wake_clear.wgsl"),
                    CORE,
                    Count::Bodies.field(),
                ),
                streams,
                &[
                    ("params", StateStream::Params.whole()),
                    ("wake_flags", StateStream::WakeFlags.whole()),
                ],
                &[],
            ),
            query: Stage::build(
                context,
                "query",
                workgroups(
                    context,
                    include_str!("../shaders/queries.wgsl"),
                    GEOMETRY_INDEX,
                ),
                streams,
                &[
                    ("queries", StateStream::QueryRecords.whole()),
                    ("body_states", StateStream::BodyStates.whole()),
                    ("body_descs", StateStream::BodyDescriptors.whole()),
                    ("colliders", StateStream::Colliders.whole()),
                    ("aabbs", RigidStream::ColliderAabbs.whole()),
                    ("entry_keys", BroadphaseStream::EntryKeys.whole()),
                    ("entry_order", BroadphaseStream::EntryOrder.whole()),
                    ("entries", BroadphaseStream::Entries.whole()),
                    ("counters", StateStream::Counters.whole()),
                    ("query_results", StateStream::QueryResults.whole()),
                    ("params", StateStream::Params.whole()),
                    ("collider_owners", StateStream::ColliderOwners.whole()),
                ],
                &dynamis_state::shape_resources(),
            ),
            observe: Stage::build(
                context,
                "observe",
                rows(
                    context,
                    include_str!("../shaders/observe.wgsl"),
                    CORE,
                    Count::Observed.field(),
                ),
                streams,
                &[
                    ("params", StateStream::Params.whole()),
                    ("observed_ids", StateStream::ObservedIds.whole()),
                    ("row_of_body", StateStream::BodyRowOfId.whole()),
                    ("body_states", StateStream::BodyStates.whole()),
                    ("observed_states", StateStream::ObservedStates.whole()),
                ],
                &[],
            ),
        }
    }

    pub fn record_query(
        &self,
        recorder: &mut ComputeRecorder,
        streams: &impl Resources,
        frame: &RigidFrame,
    ) {
        self.query
            .record_workgroups(recorder, streams, frame.query_count);
    }

    pub fn record_observe(
        &self,
        recorder: &mut ComputeRecorder,
        streams: &impl Resources,
        count: u32,
    ) {
        self.observe.record_rows(recorder, streams, count);
    }

    pub fn record(
        &self,
        recorder: &mut ComputeRecorder,
        streams: &impl Resources,
        frame: &RigidFrame,
    ) {
        self.thaw_contacts.record_stream(recorder, streams);
        self.contact_archive.record_stream(recorder, streams);
        self.archive_count_sync
            .record_workgroups(recorder, streams, 1);
        self.static_wake_clear
            .record_rows(recorder, streams, Count::Bodies.rows(&frame.params));
        self.freeze_contacts.record_stream(recorder, streams);
        self.constraint_breaks.record_rows(
            recorder,
            streams,
            Count::Constraints.rows(&frame.params),
        );
        self.joint_states
            .record_rows(recorder, streams, Count::Constraints.rows(&frame.params));
        self.record_query(recorder, streams, frame);
        self.record_observe(recorder, streams, frame.observed_count);
    }

    pub fn record_gather(&self, recorder: &mut ComputeRecorder, streams: &impl Resources) {
        self.resting_gather.record_stream(recorder, streams);
    }

    pub fn record_index(
        &self,
        recorder: &mut ComputeRecorder,
        streams: &impl Resources,
        frame: &RigidFrame,
        sort: &RadixSort,
    ) {
        self.resting_commit.record_workgroups(recorder, streams, 1);
        let words = frame.shape.body_id_words;
        let channels = sort::keyed(
            streams,
            dynamis_state::counter(COUNTER_RESTING_GATHER),
            RigidStream::RestingIndexMajor.whole(),
            RigidStream::RestingIndexMinor.whole(),
            RigidStream::RestingIndexSlots.whole(),
        );
        sort.sort(recorder, &channels, words, words);
    }
}