use crate::core::parking_lot::Mutex;
use crate::core::sparse::SparseBuffer;
use crate::{
core::scope_profile,
engine::resource_manager::DEFAULT_RESOURCE_LIFETIME,
renderer::{
cache::CacheEntry,
framework::{
geometry_buffer::{GeometryBuffer, GeometryBufferKind},
state::PipelineState,
},
},
scene::mesh::surface::SurfaceData,
};
use std::sync::Arc;
#[derive(Default)]
pub struct GeometryCache {
buffer: SparseBuffer<CacheEntry<GeometryBuffer>>,
}
impl GeometryCache {
pub fn get<'a>(
&'a mut self,
state: &mut PipelineState,
data: &Arc<Mutex<SurfaceData>>,
) -> &'a mut GeometryBuffer {
scope_profile!();
let data = data.lock();
let data_hash = data.content_hash();
if self.buffer.is_index_valid(&data.cache_entry) {
let entry = self.buffer.get_mut(&data.cache_entry).unwrap();
if data_hash != entry.value_hash {
entry.set_buffer_data(state, 0, data.vertex_buffer.raw_data());
entry
.bind(state)
.set_triangles(data.geometry_buffer.triangles_ref());
entry.value_hash = data_hash;
}
entry.time_to_live = DEFAULT_RESOURCE_LIFETIME;
entry
} else {
let geometry_buffer =
GeometryBuffer::from_surface_data(&*data, GeometryBufferKind::StaticDraw, state);
let index = self.buffer.spawn(CacheEntry {
value: geometry_buffer,
time_to_live: DEFAULT_RESOURCE_LIFETIME,
value_hash: data_hash,
});
data.cache_entry.set(index.get());
self.buffer.get_mut(&index).unwrap()
}
}
pub fn update(&mut self, dt: f32) {
scope_profile!();
for entry in self.buffer.iter_mut() {
entry.time_to_live -= dt;
}
for i in 0..self.buffer.len() {
if let Some(entry) = self.buffer.get_raw(i) {
if entry.time_to_live <= 0.0 {
self.buffer.free_raw(i);
}
}
}
}
pub fn clear(&mut self) {
self.buffer.clear();
}
}