use crate::{
graphics::{
buffer::BufferUsage, error::FrameworkError, geometry_buffer::GpuGeometryBuffer,
server::GraphicsServer,
},
renderer::{
cache::{TemporaryCache, TimeToLive},
framework::GeometryBufferExt,
},
scene::mesh::surface::{SurfaceData, SurfaceResource},
};
struct SurfaceRenderData {
buffer: GpuGeometryBuffer,
vertex_modifications_count: u64,
triangles_modifications_count: u64,
layout_hash: u64,
}
#[derive(Default)]
pub struct GeometryCache {
buffer: TemporaryCache<SurfaceRenderData>,
}
fn create_geometry_buffer(
data: &SurfaceData,
server: &dyn GraphicsServer,
) -> Result<SurfaceRenderData, FrameworkError> {
let geometry_buffer = GpuGeometryBuffer::from_surface_data(
"GeometryBuffer",
data,
BufferUsage::StaticDraw,
server,
)?;
Ok(SurfaceRenderData {
buffer: geometry_buffer,
vertex_modifications_count: data.vertex_buffer.modifications_count(),
triangles_modifications_count: data.geometry_buffer.modifications_count(),
layout_hash: data.vertex_buffer.layout_hash(),
})
}
impl GeometryCache {
pub fn get<'a>(
&'a mut self,
server: &dyn GraphicsServer,
data: &SurfaceResource,
time_to_live: TimeToLive,
) -> Result<&'a GpuGeometryBuffer, FrameworkError> {
let data = data.data_ref();
match self
.buffer
.get_entry_mut_or_insert_with(&data.cache_index, time_to_live, || {
create_geometry_buffer(&data, server)
}) {
Ok(entry) => {
if entry.layout_hash == data.vertex_buffer.layout_hash() {
if data.vertex_buffer.modifications_count() != entry.vertex_modifications_count
{
entry
.buffer
.set_buffer_data(0, data.vertex_buffer.raw_data());
entry.vertex_modifications_count = data.vertex_buffer.modifications_count();
}
if data.geometry_buffer.modifications_count()
!= entry.triangles_modifications_count
{
entry
.buffer
.set_triangles(data.geometry_buffer.triangles_ref());
entry.triangles_modifications_count =
data.geometry_buffer.modifications_count();
}
} else {
let SurfaceRenderData {
buffer,
vertex_modifications_count,
triangles_modifications_count,
layout_hash,
} = create_geometry_buffer(&data, server)?;
entry.buffer = buffer;
entry.vertex_modifications_count = vertex_modifications_count;
entry.triangles_modifications_count = triangles_modifications_count;
entry.layout_hash = layout_hash;
}
Ok(&entry.buffer)
}
Err(err) => Err(err),
}
}
pub fn update(&mut self, dt: f32) {
self.buffer.update(dt);
}
pub fn clear(&mut self) {
self.buffer.clear();
}
pub fn alive_count(&self) -> usize {
self.buffer.alive_count()
}
}