viewport_lib/resources/scivis/
curve_store.rs1use crate::resources::{
9 GlyphGpuData, PointCloudGpuData, PolylineGpuData, SpriteGpuData, StreamtubeGpuData,
10 TensorGlyphGpuData,
11};
12
13pub(crate) trait GpuByteSize {
21 fn gpu_bytes(&self) -> u64;
22}
23
24impl GpuByteSize for PolylineGpuData {
25 fn gpu_bytes(&self) -> u64 {
26 self.vertex_buffer.size() + self._uniform_buf.size()
27 }
28}
29
30impl GpuByteSize for StreamtubeGpuData {
31 fn gpu_bytes(&self) -> u64 {
32 self.vertex_buffer.size()
33 + self.index_buffer.size()
34 + self.edge_index_buffer.size()
35 + self._uniform_buf.size()
36 }
37}
38
39impl GpuByteSize for PointCloudGpuData {
40 fn gpu_bytes(&self) -> u64 {
41 self.vertex_buffer.size()
42 + self._uniform_buf.size()
43 + self._scalar_buf.size()
44 + self._colour_buf.size()
45 + self._radius_buf.size()
46 + self._transparency_buf.size()
47 }
48}
49
50impl GpuByteSize for GlyphGpuData {
51 fn gpu_bytes(&self) -> u64 {
52 self._uniform_buf.size() + self._instance_buf.size()
53 }
54}
55
56impl GpuByteSize for TensorGlyphGpuData {
57 fn gpu_bytes(&self) -> u64 {
58 self._uniform_buf.size() + self._instance_buf.size()
59 }
60}
61
62impl GpuByteSize for SpriteGpuData {
63 fn gpu_bytes(&self) -> u64 {
64 self.vertex_buffer.size() + self._uniform_buf.size() + self._instance_buf.size()
65 }
66}
67
68struct CurveSlot<T> {
70 data: Option<T>,
71 generation: u32,
72}
73
74macro_rules! curve_store {
75 ($(#[$id_doc:meta])* $id:ident, $store:ident, $data:ty) => {
76 crate::resources::handle::slot_handle! {
77 $(#[$id_doc])*
78 pub struct $id;
79 }
80
81 pub(crate) struct $store {
82 slots: Vec<CurveSlot<$data>>,
83 free_list: Vec<usize>,
84 }
85
86 impl $store {
87 pub fn new() -> Self {
88 Self { slots: Vec::new(), free_list: Vec::new() }
89 }
90
91 pub fn insert(&mut self, data: $data) -> $id {
92 if let Some(idx) = self.free_list.pop() {
93 let slot = &mut self.slots[idx];
94 slot.data = Some(data);
95 $id::new(idx as u32, slot.generation)
96 } else {
97 let idx = self.slots.len();
98 self.slots.push(CurveSlot { data: Some(data), generation: 0 });
99 $id::new(idx as u32, 0)
100 }
101 }
102
103 pub fn get(&self, id: $id) -> Option<&$data> {
104 let slot = self.slots.get(id.index())?;
105 if slot.generation != id.generation {
106 return None;
107 }
108 slot.data.as_ref()
109 }
110
111 pub fn replace(&mut self, id: $id, data: $data) -> bool {
112 match self.slots.get_mut(id.index()) {
113 Some(slot) if slot.generation == id.generation && slot.data.is_some() => {
114 slot.data = Some(data);
115 true
116 }
117 _ => false,
118 }
119 }
120
121 pub fn remove(&mut self, id: $id) -> bool {
122 if let Some(slot) = self.slots.get_mut(id.index()) {
123 if slot.generation == id.generation && slot.data.is_some() {
124 slot.data = None;
125 slot.generation = slot.generation.wrapping_add(1);
126 self.free_list.push(id.index());
127 return true;
128 }
129 }
130 false
131 }
132
133 pub fn contains(&self, id: $id) -> bool {
134 self.get(id).is_some()
135 }
136
137 #[allow(dead_code)]
138 pub fn len(&self) -> usize {
139 self.slots.iter().filter(|s| s.data.is_some()).count()
140 }
141
142 pub fn allocated_bytes(&self) -> u64 {
144 self.slots
145 .iter()
146 .filter_map(|s| s.data.as_ref())
147 .map(GpuByteSize::gpu_bytes)
148 .sum()
149 }
150 }
151 };
152}
153
154curve_store!(
155 PolylineId,
158 PolylineStore,
159 PolylineGpuData
160);
161
162curve_store!(
163 StreamtubeId,
166 StreamtubeStore,
167 StreamtubeGpuData
168);
169
170curve_store!(
171 TubeId,
174 TubeStore,
175 StreamtubeGpuData
176);
177
178curve_store!(
179 RibbonId,
182 RibbonStore,
183 StreamtubeGpuData
184);
185
186curve_store!(
187 PointCloudId,
190 PointCloudStore,
191 PointCloudGpuData
192);
193
194curve_store!(
195 GlyphSetId,
198 GlyphSetStore,
199 GlyphGpuData
200);
201
202curve_store!(
203 TensorGlyphSetId,
206 TensorGlyphSetStore,
207 TensorGlyphGpuData
208);
209
210curve_store!(
211 SpriteSetId,
215 SpriteSetStore,
216 SpriteGpuData
217);
218
219curve_store!(
220 SpriteInstanceSetId,
224 SpriteInstanceSetStore,
225 SpriteGpuData
226);