Skip to main content

dynamis_world/
snapshot.rs

1use super::World;
2use super::backend::archive::StreamArchive;
3use super::backend::registry::Planning;
4use super::body::Bodies;
5use super::body::NEVER_REPORTED;
6use super::clock::Clock;
7use super::colliders::ColliderPool;
8use super::constraint::Constraints;
9use super::query_pool::QueryPool;
10use super::shape::Shapes;
11use super::soft::SoftBodies;
12use super::view::View;
13use dynamis_abi::COUNTER_COUNT;
14use dynamis_model::PhysicsConfig;
15
16#[derive(Clone)]
17struct Scene {
18    bodies: Bodies,
19    colliders: ColliderPool,
20    constraints: Constraints,
21    shapes: Shapes,
22    soft: SoftBodies,
23}
24
25impl Scene {
26    fn capture(world: &World) -> Self {
27        Self {
28            bodies: world.bodies.clone(),
29            colliders: world.colliders.clone(),
30            constraints: world.constraints.clone(),
31            shapes: world.shapes.clone(),
32            soft: world.soft.clone(),
33        }
34    }
35
36    fn restore(&self, world: &mut World) {
37        world.bodies = self.bodies.clone();
38        world.colliders = self.colliders.clone();
39        world.constraints = self.constraints.clone();
40        world.shapes = self.shapes.clone();
41        world.soft = self.soft.clone();
42    }
43}
44
45pub struct Snapshot {
46    config: PhysicsConfig,
47    clock: Clock,
48    scene: Scene,
49    streams: StreamArchive,
50}
51
52impl World {
53    pub fn snapshot(&self) -> Snapshot {
54        self.backend.gpu.assert_alive();
55        let regions = self.backend.streams.durable_regions();
56        let bytes = dynamis_gpu::read_regions(
57            self.backend.gpu.device(),
58            self.backend.gpu.queue(),
59            "dynamis snapshot",
60            &regions,
61        );
62        Snapshot {
63            config: self.config,
64            clock: self.clock,
65            scene: Scene::capture(self),
66            streams: StreamArchive::capture(&self.backend.streams, bytes),
67        }
68    }
69
70    pub fn restore(&mut self, snapshot: &Snapshot) {
71        self.backend.gpu.assert_alive();
72        self.drain_readbacks();
73        self.config = snapshot.config;
74        self.clock = snapshot.clock;
75        snapshot.scene.restore(self);
76        self.abandon_observations();
77        self.restart_measures();
78        let live = self.live();
79        self.apply_plan(&live);
80        self.reserve_streams(&snapshot.streams);
81        self.backend
82            .streams
83            .write(self.backend.gpu.queue(), &snapshot.streams);
84    }
85
86    fn abandon_observations(&mut self) {
87        self.view = View::new();
88        self.bodies.covered.fill(NEVER_REPORTED);
89        self.events.contact.clear();
90        self.events.due.clear();
91        self.queries.pending.clear();
92        self.queries.pool = QueryPool::new();
93        self.constraints.broken.clear();
94        self.constraints.due.clear();
95    }
96
97    fn restart_measures(&mut self) {
98        self.backend.measured = [0; COUNTER_COUNT];
99        self.backend.declared.clear();
100        self.backend.measured_step = None;
101        self.backend.planning = Planning::new();
102        #[cfg(feature = "profile")]
103        self.backend.pass_timings.clear();
104    }
105
106    fn reserve_streams(&mut self, archive: &StreamArchive) {
107        let device = self.backend.gpu.device().clone();
108        let mut encoder = dynamis_gpu::SubmissionEncoder::new(&device, "dynamis snapshot reserve");
109        if self
110            .backend
111            .streams
112            .require(&device, &mut encoder, |label| archive.floor(label))
113        {
114            self.submit(encoder);
115        }
116    }
117}