Skip to main content

dynamis_rigid/
capacity.rs

1use super::streams::{RigidDemand, RigidStreams};
2use dynamis_abi::{COUNTER_EVENTS, COUNTER_SPILLOVER_EVENTS, Counters};
3use dynamis_domain::{MIN_SLOTS, StreamWatch, settled};
4
5const STREAM_DENSITY_EVENTS: u32 = 8;
6
7#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
8pub struct RigidCapacity {
9    pub events: u32,
10}
11
12#[derive(Clone, Copy, Debug)]
13pub struct RigidInputs {
14    pub bodies: u32,
15    pub colliders: u32,
16    pub collider_pool: u32,
17    pub constraints: u32,
18    pub queries: u32,
19    pub observed: u32,
20    pub ccd: bool,
21}
22
23pub fn capacity(streams: &RigidStreams) -> RigidCapacity {
24    RigidCapacity {
25        events: streams.events.slots() / dynamis_gpu::EVENT_SLOTS,
26    }
27}
28
29pub struct Capacity {
30    events: StreamWatch,
31}
32
33impl Default for Capacity {
34    fn default() -> Self {
35        Self::new()
36    }
37}
38
39impl Capacity {
40    pub const fn new() -> Self {
41        Self {
42            events: StreamWatch::IDLE,
43        }
44    }
45
46    pub fn plan(
47        &mut self,
48        measured: &Counters,
49        inputs: &RigidInputs,
50        idle: bool,
51        pairs: u32,
52        current: &RigidStreams,
53    ) -> RigidDemand {
54        self.events.observe(
55            measured[COUNTER_EVENTS],
56            measured[COUNTER_SPILLOVER_EVENTS] > 0,
57            current.events.slots() / dynamis_gpu::EVENT_SLOTS,
58        );
59        if self.events.pressured() {
60            self.events.settle(false);
61        } else if idle {
62            self.events.settle(true);
63        }
64        let event_budget =
65            dynamis_domain::product(inputs.colliders, STREAM_DENSITY_EVENTS, "event");
66        let events = if idle {
67            self.events.released(
68                current.events.slots() / dynamis_gpu::EVENT_SLOTS,
69                event_budget,
70            )
71        } else {
72            self.events.widened(
73                current.events.slots() / dynamis_gpu::EVENT_SLOTS,
74                event_budget,
75            )
76        };
77        let bodies = dynamis_domain::grown(current.body_activity.slots(), inputs.bodies, MIN_SLOTS);
78        let colliders = current
79            .collider_aabbs
80            .slots()
81            .max(inputs.collider_pool)
82            .max(MIN_SLOTS);
83        let constraints = settled(
84            idle,
85            current.constraint_rows.slots(),
86            inputs.constraints,
87            MIN_SLOTS,
88        );
89        let sort = RigidDemand::sort_slots(pairs, constraints).max(MIN_SLOTS);
90        RigidDemand {
91            bodies,
92            colliders,
93            constraints,
94            pairs,
95            events,
96            sort,
97        }
98    }
99
100    pub fn floor(pairs: u32) -> RigidDemand {
101        RigidDemand {
102            bodies: MIN_SLOTS,
103            colliders: MIN_SLOTS,
104            constraints: MIN_SLOTS,
105            pairs,
106            events: dynamis_domain::STREAM_FLOOR,
107            sort: RigidDemand::sort_slots(pairs, MIN_SLOTS).max(MIN_SLOTS),
108        }
109    }
110}