dynamis-world 0.6.0

GPU-driven physics engine
Documentation
use super::dispatch::{COMPACT_SCAN, COMPACT_SCATTER, NARROWPHASE, SORT_PAIRS};
use super::stage::{CORE, GEOMETRY, RO, RW, Stage, UNIFORM, shape_resources, whole};
use crate::dynamics::buffers::WorldBuffers;
use dynamis_gpu::{ComputeRecorder, GpuContext};
use dynamis_layout::{COUNTER_CONTACTS, COUNTER_JOINTS, COUNTER_PAIRS};
use dynamis_sort::RadixSort;

pub(super) struct Narrowphase {
    narrowphase: Stage,
    compact_scan: Stage,
    compact_offsets: Stage,
    compact_scatter: Stage,
}

impl Narrowphase {
    pub(super) fn build(context: &GpuContext, buffers: &WorldBuffers, per_row: u32) -> Self {
        Self {
            narrowphase: Stage::build(
                context,
                "narrowphase",
                include_str!("shaders/narrowphase.wgsl"),
                per_row,
                GEOMETRY,
                &[
                    (RO, whole(&buffers.bodies.states)),
                    (RO, whole(&buffers.bodies.descriptors)),
                    (RO, whole(&buffers.bodies.colliders)),
                    (RO, whole(&buffers.contacts.pairs.major)),
                    (RO, whole(&buffers.contacts.pairs.minor)),
                    (RW, whole(&buffers.contacts.raw)),
                    (RW, whole(&buffers.contacts.valid)),
                    (RW, buffers.counter(COUNTER_PAIRS)),
                    (RO, whole(&buffers.constraints.joint_major)),
                    (RO, whole(&buffers.constraints.joint_minor)),
                    (RW, buffers.counter(COUNTER_JOINTS)),
                    (UNIFORM, whole(&buffers.params)),
                ],
                &shape_resources(buffers),
            ),
            compact_scan: Stage::build(
                context,
                "compact_scan",
                include_str!("shaders/compact_scan.wgsl"),
                per_row,
                CORE,
                &[
                    (RO, whole(&buffers.contacts.valid)),
                    (RW, whole(&buffers.contacts.compact_ranks)),
                    (RW, whole(&buffers.contacts.compact_sums)),
                    (RW, buffers.counter(COUNTER_PAIRS)),
                ],
                &[],
            ),
            compact_offsets: Stage::build(
                context,
                "compact_offsets",
                include_str!("shaders/compact_offsets.wgsl"),
                per_row,
                CORE,
                &[
                    (RO, whole(&buffers.contacts.compact_sums)),
                    (RW, whole(&buffers.contacts.compact_offsets)),
                    (RW, buffers.counter(COUNTER_CONTACTS)),
                    (RW, buffers.counter(COUNTER_PAIRS)),
                ],
                &[],
            ),
            compact_scatter: Stage::build(
                context,
                "compact_scatter",
                include_str!("shaders/compact_scatter.wgsl"),
                per_row,
                CORE,
                &[
                    (RO, whole(&buffers.contacts.raw)),
                    (RO, whole(&buffers.contacts.valid)),
                    (RO, whole(&buffers.contacts.compact_ranks)),
                    (RO, whole(&buffers.contacts.compact_offsets)),
                    (RW, whole(&buffers.contacts.manifolds)),
                    (RW, whole(&buffers.contacts.contact_matched)),
                    (RW, buffers.counter(COUNTER_PAIRS)),
                ],
                &[],
            ),
        }
    }

    pub(super) fn record(
        &self,
        recorder: &mut ComputeRecorder,
        buffers: &WorldBuffers,
        sort: &RadixSort,
    ) {
        let words = buffers.collider_words();
        let channels = buffers.sort_lanes_dual(
            buffers.counter(COUNTER_PAIRS),
            &buffers.contacts.pairs.major,
            &buffers.contacts.pairs.minor,
        );
        sort.sort(
            recorder,
            &channels,
            words,
            words,
            &buffers.dispatch,
            SORT_PAIRS,
        );
        self.narrowphase
            .record_indirect(recorder, &buffers.dispatch, NARROWPHASE);
        self.compact_scan
            .record_indirect(recorder, &buffers.dispatch, COMPACT_SCAN);
        self.compact_offsets.record_workgroups(recorder, 1);
        self.compact_scatter
            .record_indirect(recorder, &buffers.dispatch, COMPACT_SCATTER);
    }
}