Better SmallCache

This commit is contained in:
Joshua Barretto 2022-08-06 18:19:43 +01:00
parent bdb71a15df
commit 9bb3681f55
2 changed files with 14 additions and 14 deletions

View File

@ -426,7 +426,7 @@ fn write_column<R: Rng>(
wpos2d: Vec2<i32>, wpos2d: Vec2<i32>,
z_range: Range<i32>, z_range: Range<i32>,
tunnel: Tunnel, tunnel: Tunnel,
mushroom_cache: &mut SmallCache<Option<Mushroom>>, mushroom_cache: &mut SmallCache<Vec3<i32>, Option<Mushroom>>,
rng: &mut R, rng: &mut R,
) { ) {
let info = canvas.info(); let info = canvas.info();
@ -494,7 +494,7 @@ fn write_column<R: Rng>(
let mut get_mushroom = |wpos: Vec3<i32>, dynamic_rng: &mut R| { let mut get_mushroom = |wpos: Vec3<i32>, dynamic_rng: &mut R| {
for (wpos2d, seed) in StructureGen2d::new(34537, 24, 8).get(wpos.xy()) { for (wpos2d, seed) in StructureGen2d::new(34537, 24, 8).get(wpos.xy()) {
let mushroom = if let Some(mushroom) = mushroom_cache let mushroom = if let Some(mushroom) = mushroom_cache
.get(wpos2d, |_| { .get(wpos2d.with_z(tunnel.a.depth), |_| {
let mut rng = RandomPerm::new(seed); let mut rng = RandomPerm::new(seed);
let (z_range, radius) = let (z_range, radius) =
tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?; tunnel.z_range_at(wpos2d.map(|e| e as f64 + 0.5), info)?;

View File

@ -1,23 +1,23 @@
use arr_macro::arr; use arr_macro::arr;
use vek::*; use vek::*;
fn calc_idx(v: Vec2<i32>) -> usize { fn calc_idx(v: impl Iterator<Item = i32>) -> usize {
let mut x = v.x as u32; let mut r = 0;
let mut y = v.y as u32; for (e, h) in v.zip([0x6eed0e9d, 0x2f72b421, 0x18132f72, 0x891e2fba].into_iter()) {
x = x.wrapping_mul(0x6eed0e9d); r ^= (e as u32).wrapping_mul(h);
y = y.wrapping_mul(0x2f72b421); }
(x ^ y) as usize r as usize
} }
// NOTE: Use 128 if TerrainChunkSize::RECT_SIZE.x = 128. // NOTE: Use 128 if TerrainChunkSize::RECT_SIZE.x = 128.
const CACHE_LEN: usize = 32; const CACHE_LEN: usize = 32;
pub struct SmallCache<V: Default> { pub struct SmallCache<K, V: Default> {
index: [Option<Vec2<i32>>; CACHE_LEN + 9], index: [Option<K>; CACHE_LEN + 9],
data: [V; CACHE_LEN + 9], data: [V; CACHE_LEN + 9],
random: u32, random: u32,
} }
impl<V: Default> Default for SmallCache<V> { impl<K: Copy, V: Default> Default for SmallCache<K, V> {
fn default() -> Self { fn default() -> Self {
Self { Self {
index: [None; CACHE_LEN + 9], index: [None; CACHE_LEN + 9],
@ -26,9 +26,9 @@ impl<V: Default> Default for SmallCache<V> {
} }
} }
} }
impl<V: Default> SmallCache<V> { impl<K: Copy + Eq + IntoIterator<Item = i32>, V: Default> SmallCache<K, V> {
pub fn get<F: FnOnce(Vec2<i32>) -> V>(&mut self, key: Vec2<i32>, f: F) -> &V { pub fn get<F: FnOnce(K) -> V>(&mut self, key: K, f: F) -> &V {
let idx = calc_idx(key) % CACHE_LEN; let idx = calc_idx(key.into_iter()) % CACHE_LEN;
// Search // Search
if self.index[idx].as_ref().map(|k| k == &key).unwrap_or(false) { if self.index[idx].as_ref().map(|k| k == &key).unwrap_or(false) {