use crate::resources::{
GlyphGpuData, PointCloudGpuData, PolylineGpuData, SpriteGpuData, StreamtubeGpuData,
TensorGlyphGpuData,
};
pub(crate) trait GpuByteSize {
fn gpu_bytes(&self) -> u64;
}
impl GpuByteSize for PolylineGpuData {
fn gpu_bytes(&self) -> u64 {
self.vertex_buffer.size() + self._uniform_buf.size()
}
}
impl GpuByteSize for StreamtubeGpuData {
fn gpu_bytes(&self) -> u64 {
self.vertex_buffer.size()
+ self.index_buffer.size()
+ self.edge_index_buffer.size()
+ self._uniform_buf.size()
}
}
impl GpuByteSize for PointCloudGpuData {
fn gpu_bytes(&self) -> u64 {
self.vertex_buffer.size()
+ self._uniform_buf.size()
+ self._scalar_buf.size()
+ self._colour_buf.size()
+ self._radius_buf.size()
+ self._transparency_buf.size()
}
}
impl GpuByteSize for GlyphGpuData {
fn gpu_bytes(&self) -> u64 {
self._uniform_buf.size() + self._instance_buf.size()
}
}
impl GpuByteSize for TensorGlyphGpuData {
fn gpu_bytes(&self) -> u64 {
self._uniform_buf.size() + self._instance_buf.size()
}
}
impl GpuByteSize for SpriteGpuData {
fn gpu_bytes(&self) -> u64 {
self.vertex_buffer.size() + self._uniform_buf.size() + self._instance_buf.size()
}
}
struct CurveSlot<T> {
data: Option<T>,
generation: u32,
}
macro_rules! curve_store {
($(#[$id_doc:meta])* $id:ident, $store:ident, $data:ty) => {
crate::resources::handle::slot_handle! {
$(#[$id_doc])*
pub struct $id;
}
pub(crate) struct $store {
slots: Vec<CurveSlot<$data>>,
free_list: Vec<usize>,
}
impl $store {
pub fn new() -> Self {
Self { slots: Vec::new(), free_list: Vec::new() }
}
pub fn insert(&mut self, data: $data) -> $id {
if let Some(idx) = self.free_list.pop() {
let slot = &mut self.slots[idx];
slot.data = Some(data);
$id::new(idx as u32, slot.generation)
} else {
let idx = self.slots.len();
self.slots.push(CurveSlot { data: Some(data), generation: 0 });
$id::new(idx as u32, 0)
}
}
pub fn get(&self, id: $id) -> Option<&$data> {
let slot = self.slots.get(id.index())?;
if slot.generation != id.generation {
return None;
}
slot.data.as_ref()
}
pub fn replace(&mut self, id: $id, data: $data) -> bool {
match self.slots.get_mut(id.index()) {
Some(slot) if slot.generation == id.generation && slot.data.is_some() => {
slot.data = Some(data);
true
}
_ => false,
}
}
pub fn remove(&mut self, id: $id) -> bool {
if let Some(slot) = self.slots.get_mut(id.index()) {
if slot.generation == id.generation && slot.data.is_some() {
slot.data = None;
slot.generation = slot.generation.wrapping_add(1);
self.free_list.push(id.index());
return true;
}
}
false
}
pub fn contains(&self, id: $id) -> bool {
self.get(id).is_some()
}
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.slots.iter().filter(|s| s.data.is_some()).count()
}
pub fn allocated_bytes(&self) -> u64 {
self.slots
.iter()
.filter_map(|s| s.data.as_ref())
.map(GpuByteSize::gpu_bytes)
.sum()
}
}
};
}
curve_store!(
PolylineId,
PolylineStore,
PolylineGpuData
);
curve_store!(
StreamtubeId,
StreamtubeStore,
StreamtubeGpuData
);
curve_store!(
TubeId,
TubeStore,
StreamtubeGpuData
);
curve_store!(
RibbonId,
RibbonStore,
StreamtubeGpuData
);
curve_store!(
PointCloudId,
PointCloudStore,
PointCloudGpuData
);
curve_store!(
GlyphSetId,
GlyphSetStore,
GlyphGpuData
);
curve_store!(
TensorGlyphSetId,
TensorGlyphSetStore,
TensorGlyphGpuData
);
curve_store!(
SpriteSetId,
SpriteSetStore,
SpriteGpuData
);
curve_store!(
SpriteInstanceSetId,
SpriteInstanceSetStore,
SpriteGpuData
);