mesh_sieve/accelerator/
section.rs1use crate::data::section::Section;
4use crate::data::storage::Storage;
5
6use super::plan::{checked_u32, upload};
7use super::{AcceleratorBackend, AcceleratorError, DeviceBuffer, DeviceValue};
8
9pub struct DeviceSection<T: DeviceValue, B: AcceleratorBackend> {
11 pub atlas_version: u64,
13 pub topology_version: u64,
15 pub offsets: B::Buffer<u32>,
17 pub lengths: B::Buffer<u32>,
19 pub values: B::Buffer<T>,
21 pub point_count: usize,
23 pub value_count: usize,
25}
26
27impl<T: DeviceValue, B: AcceleratorBackend> DeviceSection<T, B> {
28 pub fn upload_from<S: Storage<T>>(
30 backend: &B,
31 section: &Section<T, S>,
32 topology_version: u64,
33 ) -> Result<Self, AcceleratorError> {
34 checked_u32(section.atlas().len(), "atlas point count")?;
35 checked_u32(section.atlas().total_len(), "section value count")?;
36 let mut offsets = Vec::with_capacity(section.atlas().len());
37 let mut lengths = Vec::with_capacity(section.atlas().len());
38 for (offset, len) in section.atlas().iter_spans() {
39 offsets.push(checked_u32(offset, "atlas offset")?);
40 lengths.push(checked_u32(len, "atlas slice length")?);
41 }
42 Ok(Self {
43 atlas_version: section.atlas().version(),
44 topology_version,
45 offsets: upload(backend, &offsets)?,
46 lengths: upload(backend, &lengths)?,
47 values: upload(backend, section.as_flat_slice())?,
48 point_count: section.atlas().len(),
49 value_count: section.atlas().total_len(),
50 })
51 }
52
53 pub fn refresh_values_from<S: Storage<T>>(
55 &mut self,
56 backend: &B,
57 section: &Section<T, S>,
58 topology_version: u64,
59 ) -> Result<(), AcceleratorError> {
60 self.validate(section.atlas().version(), topology_version)?;
61 if section.as_flat_slice().len() != self.values.len() {
62 return Err(AcceleratorError::LengthMismatch {
63 expected: self.values.len(),
64 found: section.as_flat_slice().len(),
65 });
66 }
67 backend
68 .upload_into(section.as_flat_slice(), &mut self.values)
69 .map_err(|e| AcceleratorError::DeviceTransferFailed(e.to_string()))
70 }
71
72 pub fn download_into<S: Storage<T> + Clone>(
74 &self,
75 backend: &B,
76 section: &mut Section<T, S>,
77 topology_version: u64,
78 ) -> Result<(), AcceleratorError>
79 where
80 T: Clone + Default,
81 {
82 self.validate(section.atlas().version(), topology_version)?;
83 let mut host = vec![T::zeroed(); self.value_count];
84 backend
85 .download(&self.values, &mut host)
86 .map_err(|e| AcceleratorError::DeviceTransferFailed(e.to_string()))?;
87 section
88 .try_scatter_in_order(&host)
89 .map_err(|e| AcceleratorError::InvalidPlan(e.to_string()))
90 }
91
92 pub fn validate(
94 &self,
95 atlas_version: u64,
96 topology_version: u64,
97 ) -> Result<(), AcceleratorError> {
98 if self.atlas_version != atlas_version {
99 return Err(AcceleratorError::StaleAtlasPlan {
100 expected: self.atlas_version,
101 found: atlas_version,
102 });
103 }
104 if self.topology_version != topology_version {
105 return Err(AcceleratorError::StaleTopologyPlan {
106 expected: self.topology_version,
107 found: topology_version,
108 });
109 }
110 Ok(())
111 }
112}