celestialsim/chunk_nodes/
mod.rs1use celestial_graph::{GraphNode, NodeDesc, NodeId, Graph};
11
12use crate::chunk_pipeline::ChunkCtx;
13
14mod upload;
15mod surface_custom;
16mod realize;
17mod bake;
18mod scatter_place;
19mod scatter_compact;
20
21pub use upload::ChunkUpload;
22pub use surface_custom::ChunkSurfaceCustom;
23pub use realize::ChunkRealize;
24pub use bake::ChunkBake;
25pub use scatter_place::ChunkScatterPlace;
26pub use scatter_compact::ChunkScatterCompact;
27
28pub trait ChunkNode {
31 fn name(&self) -> &'static str;
33 fn params_hash(&self) -> u64 {
36 0
37 }
38 fn record(&mut self, ctx: &mut ChunkCtx<'_>);
40}
41
42impl<'a> GraphNode<ChunkCtx<'a>> for Box<dyn ChunkNode> {
44 fn params_hash(&self) -> u64 {
45 (**self).params_hash()
46 }
47 fn record(&mut self, ctx: &mut ChunkCtx<'a>) {
48 (**self).record(ctx)
49 }
50}
51
52const R_CHUNK_DESC: usize = 0;
55const R_INSTANCES: usize = 1;
56const R_VERTS_TEX: usize = 2;
57const R_ATLAS: usize = 3;
58const R_SCATTER_VIS: usize = 4;
60const R_SCATTER_POOL: usize = 5;
62const R_SCATTER_OUT: usize = 6;
64const R_SURFACE: usize = 7;
67const RESOURCE_COUNT: usize = 8;
68
69struct NodeSpec {
72 make: fn() -> Box<dyn ChunkNode>,
73 reads: Vec<usize>,
74 writes: Vec<usize>,
75}
76
77fn pipeline_specs() -> Vec<NodeSpec> {
79 vec![
80 NodeSpec {
81 make: || Box::new(ChunkUpload),
82 reads: vec![],
83 writes: vec![R_CHUNK_DESC, R_INSTANCES, R_SCATTER_VIS],
84 },
85 NodeSpec {
89 make: || Box::new(ChunkSurfaceCustom),
90 reads: vec![R_CHUNK_DESC],
91 writes: vec![R_SURFACE],
92 },
93 NodeSpec {
94 make: || Box::new(ChunkRealize),
95 reads: vec![R_CHUNK_DESC, R_SURFACE],
96 writes: vec![R_VERTS_TEX],
97 },
98 NodeSpec {
99 make: || Box::new(ChunkBake),
100 reads: vec![R_CHUNK_DESC, R_SURFACE],
101 writes: vec![R_ATLAS],
102 },
103 NodeSpec {
104 make: || Box::new(ChunkScatterPlace),
105 reads: vec![R_CHUNK_DESC, R_SURFACE],
108 writes: vec![R_SCATTER_POOL],
109 },
110 NodeSpec {
111 make: || Box::new(ChunkScatterCompact),
112 reads: vec![R_SCATTER_POOL, R_SCATTER_VIS],
113 writes: vec![R_SCATTER_OUT],
114 },
115 ]
116}
117
118pub struct ChunkRegistry {
120 pub upload: NodeId,
122 pub realize: NodeId,
124}
125
126pub fn build_chunk_pipeline(graph: &mut Graph<Box<dyn ChunkNode>>) -> ChunkRegistry {
129 let resources: Vec<_> = (0..RESOURCE_COUNT).map(|_| graph.add_resource()).collect();
130 let mut by_name: std::collections::HashMap<&'static str, NodeId> = Default::default();
131 for spec in pipeline_specs() {
132 let node = (spec.make)();
133 let name = node.name();
134 let id = graph.add_node(
135 NodeDesc {
136 name,
137 reads: spec.reads.iter().map(|&s| resources[s]).collect(),
138 writes: spec.writes.iter().map(|&s| resources[s]).collect(),
139 },
140 node,
141 );
142 by_name.insert(name, id);
143 }
144 ChunkRegistry {
145 upload: by_name["celestial/chunk-upload"],
146 realize: by_name["celestial/chunk-realize"],
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
157 fn chunk_registry_topology_is_locked() {
158 let specs = pipeline_specs();
159 let by_name: std::collections::HashMap<&'static str, &NodeSpec> =
160 specs.iter().map(|s| ((s.make)().name(), s)).collect();
161 let names: Vec<&'static str> = specs.iter().map(|s| (s.make)().name()).collect();
162 assert_eq!(
163 names,
164 [
165 "celestial/chunk-upload",
166 "celestial/chunk-surface-custom",
167 "celestial/chunk-realize",
168 "celestial/chunk-bake",
169 "celestial/chunk-scatter-place",
170 "celestial/chunk-scatter-compact",
171 ]
172 );
173
174 let n = |name| by_name[name];
175 assert_eq!(n("celestial/chunk-upload").reads, Vec::<usize>::new());
177 assert_eq!(
178 n("celestial/chunk-upload").writes,
179 vec![R_CHUNK_DESC, R_INSTANCES, R_SCATTER_VIS]
180 );
181 assert_eq!(n("celestial/chunk-surface-custom").reads, vec![R_CHUNK_DESC]);
184 assert_eq!(n("celestial/chunk-surface-custom").writes, vec![R_SURFACE]);
185 assert_eq!(n("celestial/chunk-realize").reads, vec![R_CHUNK_DESC, R_SURFACE]);
187 assert_eq!(n("celestial/chunk-realize").writes, vec![R_VERTS_TEX]);
188 assert_eq!(n("celestial/chunk-bake").reads, vec![R_CHUNK_DESC, R_SURFACE]);
191 assert_eq!(n("celestial/chunk-bake").writes, vec![R_ATLAS]);
192 assert_eq!(
195 n("celestial/chunk-scatter-place").reads,
196 vec![R_CHUNK_DESC, R_SURFACE]
197 );
198 assert_eq!(n("celestial/chunk-scatter-place").writes, vec![R_SCATTER_POOL]);
199 assert_eq!(
202 n("celestial/chunk-scatter-compact").reads,
203 vec![R_SCATTER_POOL, R_SCATTER_VIS]
204 );
205 assert_eq!(n("celestial/chunk-scatter-compact").writes, vec![R_SCATTER_OUT]);
206 }
207}