mesh_sieve/accelerator/
plan.rs1use std::collections::HashMap;
4
5use crate::topology::bounds::PayloadLike;
6use crate::topology::point::PointId;
7use crate::topology::sieve::FrozenSieveCsr;
8
9use super::{AcceleratorBackend, AcceleratorError, DeviceValue};
10
11#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
13pub struct PlanEpochs {
14 pub topology: u64,
16 pub atlas: u64,
18 pub geometry: u64,
20}
21
22impl PlanEpochs {
23 pub fn validate(self, current: Self) -> Result<(), AcceleratorError> {
25 if self.topology != current.topology {
26 return Err(AcceleratorError::StaleTopologyPlan {
27 expected: self.topology,
28 found: current.topology,
29 });
30 }
31 if self.atlas != current.atlas {
32 return Err(AcceleratorError::StaleAtlasPlan {
33 expected: self.atlas,
34 found: current.atlas,
35 });
36 }
37 if self.geometry != current.geometry {
38 return Err(AcceleratorError::StaleGeometryPlan {
39 expected: self.geometry,
40 found: current.geometry,
41 });
42 }
43 Ok(())
44 }
45}
46
47pub struct DeviceTopology<B: AcceleratorBackend> {
49 pub topology_version: u64,
51 pub point_ids: B::Buffer<u64>,
53 pub cone_offsets: B::Buffer<u32>,
55 pub cone_points: B::Buffer<u32>,
57 pub support_offsets: B::Buffer<u32>,
59 pub support_points: B::Buffer<u32>,
61 pub point_count: usize,
63 pub incidence_count: usize,
65}
66
67pub struct DeviceMeshPlan<B: AcceleratorBackend> {
70 pub topology: DeviceTopology<B>,
72 pub index_of: HashMap<PointId, u32>,
74}
75
76impl<B: AcceleratorBackend> DeviceMeshPlan<B> {
77 pub fn compile<T: PayloadLike>(
79 backend: &B,
80 frozen: &FrozenSieveCsr<PointId, T>,
81 topology_version: u64,
82 ) -> Result<Self, AcceleratorError> {
83 checked_u32(frozen.point_of.len(), "point count")?;
84 checked_u32(frozen.out_dsts.len(), "cone incidence count")?;
85 checked_u32(frozen.in_srcs.len(), "support incidence count")?;
86 let point_ids: Vec<u64> = frozen.point_of.iter().map(PointId::get).collect();
87 let upload = |result: Result<B::Buffer<u32>, B::Error>| {
88 result.map_err(|e| AcceleratorError::DeviceTransferFailed(e.to_string()))
89 };
90 let point_ids = backend
91 .upload(&point_ids)
92 .map_err(|e| AcceleratorError::DeviceTransferFailed(e.to_string()))?;
93 let cone_offsets = upload(backend.upload(&frozen.out_offsets))?;
94 let cone_points = upload(backend.upload(&frozen.out_dsts))?;
95 let support_offsets = upload(backend.upload(&frozen.in_offsets))?;
96 let support_points = upload(backend.upload(&frozen.in_srcs))?;
97 Ok(Self {
98 topology: DeviceTopology {
99 topology_version,
100 point_ids,
101 cone_offsets,
102 cone_points,
103 support_offsets,
104 support_points,
105 point_count: frozen.point_of.len(),
106 incidence_count: frozen.out_dsts.len(),
107 },
108 index_of: frozen.index_of.clone(),
109 })
110 }
111
112 pub fn validate_topology(&self, current: u64) -> Result<(), AcceleratorError> {
114 if self.topology.topology_version == current {
115 Ok(())
116 } else {
117 Err(AcceleratorError::StaleTopologyPlan {
118 expected: self.topology.topology_version,
119 found: current,
120 })
121 }
122 }
123}
124
125pub(crate) fn checked_u32(value: usize, what: &'static str) -> Result<u32, AcceleratorError> {
126 u32::try_from(value).map_err(|_| AcceleratorError::IndexOverflow { what, value })
127}
128
129pub(crate) fn upload<T: DeviceValue, B: AcceleratorBackend>(
130 backend: &B,
131 values: &[T],
132) -> Result<B::Buffer<T>, AcceleratorError> {
133 backend
134 .upload(values)
135 .map_err(|e| AcceleratorError::DeviceTransferFailed(e.to_string()))
136}