From c4f2cae04a3b03ad305895afe502ad773ac9d7f3 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Fri, 8 Jul 2022 19:11:16 -0700 Subject: [PATCH] Minor fixes (e.g. snow not filling in sprites). --- Cargo.lock | 5 +++-- common/Cargo.toml | 4 +++- common/src/terrain/chonk.rs | 17 ++++++++++------- world/Cargo.toml | 2 +- world/src/lib.rs | 25 +++++++++++++++++-------- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc29808817..633ee916a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -456,9 +456,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "bytecheck" @@ -6502,6 +6502,7 @@ dependencies = [ "approx 0.4.0", "bitflags", "bitvec", + "bumpalo", "bytemuck", "chrono", "chrono-tz", diff --git a/common/Cargo.toml b/common/Cargo.toml index 115ab0881e..cd5d4f65b6 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -40,7 +40,9 @@ strum = { version = "0.24", features = ["derive"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] approx = "0.4.0" bitvec = "0.22" -# bumpalo = { version = "3.9.1", features = ["allocator_api"] } +bumpalo = { version = "3.10.0", features = [ + # "allocator_api" + ] } bytemuck = { version="1.4", features=["derive"] } clap = "2.33" crossbeam-utils = "0.8.1" diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs index 5960c46127..6ccae83dad 100644 --- a/common/src/terrain/chonk.rs +++ b/common/src/terrain/chonk.rs @@ -6,6 +6,7 @@ use crate::{ volumes::chunk::{Chunk, ChunkError, ChunkPosIter, ChunkVolIter}, }; use core::{hash::Hash, marker::PhantomData}; +use hashbrown::HashMap; use serde::{Deserialize, Serialize}; use vek::*; @@ -102,20 +103,22 @@ impl>, S: RectVolSize, M: Clone> C /// /// It's not acutally flat, it just skips the indirection through the index. The idea is to /// use a constant stride for row access so the prefetcher can process it more easily. - pub fn make_flat<'a>(&'a self, below_slice: &'a [V], above_slice: &'a [V]) -> Vec<&'a [V]> + pub fn make_flat<'a>(&'a self, arena: &'a bumpalo::Bump) -> Vec<&'a [V]> where - V: Copy + Eq, + V: Copy + Hash + Eq, [(); SubChunk::::GROUP_VOLUME as usize]:, { + // Cache of slices per block type to maximize cacheline reuse. + let mut default_slices = HashMap::new(); let mut flat = Vec::with_capacity(self.sub_chunks.len() * /*SubChunkSize::::SIZE.z as usize **/ /* SubChunk::::VOLUME as usize */ SubChunk::::GROUP_COUNT_TOTAL as usize); self.sub_chunks.iter().enumerate().for_each(|(idx, sub_chunk)| { - let slice = if sub_chunk.default() == &self.below { - below_slice - } else { - above_slice - }; + let default = *sub_chunk.default(); + let slice = *default_slices.entry(default) + .or_insert_with(move || { + &*arena.alloc_slice_fill_copy(SubChunk::::GROUP_VOLUME as usize, default) + }); sub_chunk.push_flat(&mut flat, slice); }); flat diff --git a/world/Cargo.toml b/world/Cargo.toml index ee8798277f..43b620c21d 100644 --- a/world/Cargo.toml +++ b/world/Cargo.toml @@ -21,7 +21,7 @@ common-net = { package = "veloren-common-net", path = "../common/net" } bincode = "1.3.1" bitvec = "0.22" -bumpalo = "3.9.1" +bumpalo = "3.10.0" enum-iterator = "0.7" fxhash = "0.2.1" image = { version = "0.24", default-features = false, features = ["png"] } diff --git a/world/src/lib.rs b/world/src/lib.rs index c69684ab9c..187ef7ba05 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -543,15 +543,17 @@ impl World { ) }); - // Apply snow cover. + // Defragment to minimize space consumption. + chunk.defragment(); + + // Apply snow cover (we do this after defragmentation to benefit from faster iteration over + // air underground). if has_snow { let snow = Block::new(BlockKind::Snow, Rgb::new(210, 210, 255)); // NOTE: We assume throughout Veloren that u32 fits in usize (we need to make this a static // assertion). RECT_SIZE.product() is statically valid. let mut snow_blocks = Vec::with_capacity(TerrainChunkSize::RECT_SIZE.product() as usize * 3); - let air_slice = [air; common::terrain::TerrainSubChunk::GROUP_VOLUME as usize]; - let stone_slice = [stone; common::terrain::TerrainSubChunk::GROUP_VOLUME as usize]; - let flat = chunk.make_flat(&stone_slice, &air_slice); + let flat = chunk.make_flat(/*&stone_slice, &air_slice, */&arena); zcache_grid.iter() .filter(|(_, col_sample)| col_sample.snow_cover) .for_each(|(wpos_delta, col_sample)| { @@ -597,15 +599,22 @@ impl World { } } */ }); + arena.reset(); snow_blocks.into_iter().for_each(|pos| { - let _ = chunk.set(pos, snow); + // Make sure not to replace sprites. + // + // Note that we don't check this in the inner loop above because we want snow to + // fall through sprites, and in practice the block.is_air() check is pretty + // effective. + let _ = chunk.map(pos, |block| if block == Block::empty() { + snow + } else { + block + }); }); } - // Finally, defragment to minimize space consumption. - chunk.defragment(); - Ok((chunk, supplement)) }