Higher level cache abstraction

This commit is contained in:
Imbris 2019-10-01 02:09:27 -04:00
parent 89a1c45ac7
commit 83b5ca3335
2 changed files with 67 additions and 34 deletions

View File

@ -3,7 +3,7 @@ use crate::{
volumes::dyna::DynaError,
};
use hashbrown::{hash_map, HashMap};
use std::{fmt::Debug, sync::Arc};
use std::{fmt::Debug, ops::Deref, sync::Arc};
use vek::*;
#[derive(Debug, Clone)]
@ -159,29 +159,58 @@ impl<V: RectRasterableVol> VolGrid2d<V> {
iter: self.chunks.iter(),
}
}
pub fn cached<'a>(&'a self) -> CachedVolGrid2d<'a, V> {
CachedVolGrid2d::new(self)
}
}
impl<V: RectRasterableVol + ReadVol> VolGrid2d<V> {
pub struct CachedVolGrid2d<'a, V: RectRasterableVol> {
vol_grid_2d: &'a VolGrid2d<V>,
cache: Option<(Vec2<i32>, Arc<V>)>,
}
impl<'a, V: RectRasterableVol> CachedVolGrid2d<'a, V> {
pub fn new(vol_grid_2d: &'a VolGrid2d<V>) -> Self {
Self {
vol_grid_2d,
cache: None,
}
}
}
impl<'a, V: RectRasterableVol + ReadVol> CachedVolGrid2d<'a, V> {
// Note: this may be invalidated by mutations of the chunks hashmap
#[inline(always)]
pub fn get_vox_cached<'a>(
&'a self,
pos: Vec3<i32>,
cache: &'a mut Option<(Vec2<i32>, Arc<V>)>,
) -> Result<&V::Vox, VolGrid2dError<V>> {
let ck = Self::chunk_key(pos);
let chunk = if cache.as_ref().map(|(key, _)| *key == ck).unwrap_or(false) {
&cache.as_ref().unwrap().1
pub fn get(&mut self, pos: Vec3<i32>) -> Result<&V::Vox, VolGrid2dError<V>> {
let ck = VolGrid2d::<V>::chunk_key(pos);
let chunk = if self
.cache
.as_ref()
.map(|(key, _)| *key == ck)
.unwrap_or(false)
{
&self.cache.as_ref().unwrap().1
} else {
let chunk = self.chunks.get(&ck).ok_or(VolGrid2dError::NoSuchChunk)?;
*cache = Some((ck, chunk.clone()));
let chunk = self
.vol_grid_2d
.chunks
.get(&ck)
.ok_or(VolGrid2dError::NoSuchChunk)?;
self.cache = Some((ck, chunk.clone()));
chunk
};
let co = Self::chunk_offs(pos);
let co = VolGrid2d::<V>::chunk_offs(pos);
chunk.get(co).map_err(VolGrid2dError::ChunkError)
}
}
impl<'a, V: RectRasterableVol> Deref for CachedVolGrid2d<'a, V> {
type Target = VolGrid2d<V>;
fn deref(&self) -> &Self::Target {
self.vol_grid_2d
}
}
pub struct ChunkIter<'a, V: RectRasterableVol> {
iter: hash_map::Iter<'a, Vec2<i32>, Arc<V>>,
}

View File

@ -41,7 +41,7 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
max: bounds.max + sunlight,
};
let mut get_cache = None;
let mut vol_cached = vol.cached();
let mut voids = HashMap::new();
let mut rays = vec![outer.size().d; outer.size().product() as usize];
@ -49,8 +49,8 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
for y in 0..outer.size().h {
let mut outside = true;
for z in (0..outer.size().d).rev() {
let block = vol
.get_vox_cached(outer.min + Vec3::new(x, y, z), &mut get_cache)
let block = vol_cached
.get(outer.min + Vec3::new(x, y, z))
.ok()
.copied()
.unwrap_or(Block::empty());
@ -140,10 +140,10 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
let mut opaque_mesh = Mesh::new();
let mut fluid_mesh = Mesh::new();
let mut get_cache = None;
let light = calc_light(range, self);
let mut vol_cached = self.cached();
for x in range.min.x + 1..range.max.x - 1 {
for y in range.min.y + 1..range.max.y - 1 {
let mut lights = [[[0.0; 3]; 3]; 3];
@ -159,25 +159,26 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
}
}
macro_rules! get_color {
($pos:expr) => {
self.get_vox_cached($pos, &mut get_cache)
.ok()
.filter(|vox| vox.is_opaque())
.and_then(|vox| vox.get_color())
.map(|col| Rgba::from_opaque(col))
.unwrap_or(Rgba::zero())
};
let get_color = |maybe_block: Option<&Block>| {
maybe_block
.filter(|vox| vox.is_opaque())
.and_then(|vox| vox.get_color())
.map(|col| Rgba::from_opaque(col))
.unwrap_or(Rgba::zero())
};
let mut colors = [[[Rgba::zero(); 3]; 3]; 3];
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
colors[k][j][i] = get_color!(
Vec3::new(x, y, range.min.z)
+ Vec3::new(i as i32, j as i32, k as i32)
- 1
colors[k][j][i] = get_color(
vol_cached
.get(
Vec3::new(x, y, range.min.z)
+ Vec3::new(i as i32, j as i32, k as i32)
- 1,
)
.ok(),
);
}
}
@ -199,12 +200,15 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
}
for i in 0..3 {
for j in 0..3 {
colors[2][j][i] =
get_color!(pos + Vec3::new(i as i32, j as i32, 2) - 1);
colors[2][j][i] = get_color(
vol_cached
.get(pos + Vec3::new(i as i32, j as i32, 2) - 1)
.ok(),
);
}
}
let block = self.get_vox_cached(pos, &mut get_cache).ok();
let block = vol_cached.get(pos).ok();
// Create mesh polygons
if block.map(|vox| vox.is_opaque()).unwrap_or(false) {