dynamis_world/
snapshot.rs1use 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 ®ions,
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}