diff --git a/common/src/figure/cell.rs b/common/src/figure/cell.rs index 0cc010e25a..9fea2c2ed0 100644 --- a/common/src/figure/cell.rs +++ b/common/src/figure/cell.rs @@ -25,6 +25,12 @@ impl CellData { } pub fn is_hollow(&self) -> bool { self.attr.get() & HOLLOW != 0 } + + #[inline(always)] + pub fn is_glowy(&self) -> bool { self.attr.get() & GLOWY != 0 } + + #[inline(always)] + pub fn is_shiny(&self) -> bool { self.attr.get() & SHINY != 0 } } impl Default for CellData { @@ -73,8 +79,10 @@ impl Cell { } impl Vox for Cell { + #[inline(always)] fn empty() -> Self { Cell::Empty } + #[inline(always)] fn is_empty(&self) -> bool { match self { Cell::Filled(_) => false, diff --git a/common/src/volumes/dyna.rs b/common/src/volumes/dyna.rs index c51666a35c..0a9728b366 100644 --- a/common/src/volumes/dyna.rs +++ b/common/src/volumes/dyna.rs @@ -160,13 +160,13 @@ pub struct ColumnAccess; impl Access for ColumnAccess { fn idx(pos: Vec3, sz: Vec3) -> usize { - (pos.x * sz.y as i32 * sz.z as i32 + pos.y * sz.z as i32 + pos.z) as usize + ((pos.z * sz.y as i32 + pos.y) * sz.x as i32 + pos.x) as usize } fn pos(idx: usize, sz: Vec3) -> Vec3 { - let z = idx as u32 % sz.z; - let y = (idx as u32 / sz.z) % sz.y; - let x = idx as u32 / (sz.y * sz.z); + let x = idx as u32 % sz.x; + let y = (idx as u32 / sz.x) % sz.y; + let z = idx as u32 / (sz.y * sz.x); Vec3::new(x, y, z).map(|e| e as i32) } } diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 86c43540aa..6f6c712bde 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -1,5 +1,4 @@ #![deny(unsafe_code)] -#![feature(bool_to_option)] #![recursion_limit = "2048"] #[cfg(all( diff --git a/voxygen/src/mesh/segment.rs b/voxygen/src/mesh/segment.rs index 2219f153e8..45c42ae7af 100644 --- a/voxygen/src/mesh/segment.rs +++ b/voxygen/src/mesh/segment.rs @@ -49,46 +49,89 @@ where assert!(greedy_size.x <= 512 && greedy_size.y <= 512 && greedy_size.z <= 512); // NOTE: Cast to usize is safe because of previous check, since all values fit // into u16 which is safe to cast to usize. + + let (flat, flat_get) = { + let (w_, h_, d_) = greedy_size.into_tuple(); + let (w, h, d) = (w_ + 2, h_ + 2, d_ + 2); + let wh = w * h; + let flat = { + let mut flat_ = vec![Cell::empty(); (d * wh) as usize]; + let flat = &mut flat_[0..(d * wh) as usize]; + // NOTE: We can skip the outside edges because we know they're already empty. + flat.chunks_exact_mut(wh as usize).skip(1).take(d_ as usize).enumerate().for_each(|(z, flat)| { + let z = z as i32; + flat.chunks_exact_mut(w as usize).skip(1).take(h_ as usize).enumerate().for_each(|(y, flat)| { + let y = y as i32; + flat.into_iter().skip(1).take(w_ as usize).enumerate().for_each(|(x, flat)| { + let x = x as i32; + *flat = vol.get(Vec3::new(x, y, z)).copied().unwrap_or_else(|_| Cell::empty()); + }); + }); + }); + /* for z in -1..greedy_size.z + 1 { + for y in -1..greedy_size.y + 1 { + for x in -1..greedy_size.x + 1 { + let wpos = lower_bound + Vec3::new(x, y, z); + let block = vol.get(wpos).map(|b| *b).unwrap_or_else(|_| Cell::empty()); + flat[i] = block; + i += 1; + } + } + } */ + flat_ + }; + + let wh = w * h; + // let offset = wh + w + 1; + let flat_get = #[inline(always)] move |flat: &Vec, Vec3 { x, y, z }| /* match flat + .get((x * hd + y * d + z) as usize) + .copied() + { + Some(b) => b, + None => panic!("x {} y {} z {} d {} h {}", x, y, z, d, h), + }*/flat[(/*offset + */z * wh + y * w + x) as usize]; + + (flat, flat_get) + }; + let greedy_size = greedy_size.as_::(); let greedy_size_cross = greedy_size; - let draw_delta = lower_bound; + let draw_delta = lower_bound + 1; - let get_light = |vol: &mut V, pos: Vec3| { - if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) { + let get_light = #[inline(always)] move |flat: &mut _, pos: Vec3| { + if flat_get(flat, pos).is_empty() { 1.0 } else { 0.0 } }; - let get_glow = |_vol: &mut V, _pos: Vec3| 0.0; - let get_opacity = |vol: &mut V, pos: Vec3| vol.get(pos).map_or(true, |vox| vox.is_empty()); - let should_draw = |vol: &mut V, pos: Vec3, from: Cell, to: Cell, /*delta: Vec3, */uv| { + let get_glow = #[inline(always)] |_flat: &mut _, _pos: Vec3| 0.0; + let get_opacity = #[inline(always)] move |flat: &mut _, pos: Vec3| flat_get(flat, pos).is_empty(); + let should_draw = #[inline(always)] |_flat: &mut _, pos: Vec3, from: Cell, to: Cell, /*delta: Vec3, */uv| { should_draw_greedy(pos, from, to,/* delta, */uv/*, |vox| { vol.get(vox) .map(|vox| *vox) .unwrap_or_else(|_| Cell::empty()) } */) }; - let create_opaque = |atlas_pos, pos, norm| { + let create_opaque = #[inline(always)] |atlas_pos, pos, norm| { TerrainVertex::new_figure(atlas_pos, (pos + offs) * scale, norm, bone_idx) }; greedy.push(GreedyConfig { - data: vol, + data: flat, draw_delta, greedy_size, greedy_size_cross, - get_vox: |vol: &mut V, vox| { - vol.get(vox) - .map(|vox| *vox) - .unwrap_or_else(|_| Cell::empty()) + get_vox: #[inline(always)] move |flat: &mut _, vox| { + flat_get(flat, vox) }, - get_ao: |_: &mut V, _: Vec3| 1.0, + get_ao: #[inline(always)] |_: &mut _, _: Vec3| 1.0, get_light, get_glow, get_opacity, should_draw, - push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| { + push_quad: #[inline(always)] |atlas_origin, dim, origin, draw_dim, norm, meta: &()| { opaque_mesh.push_quad(greedy::create_quad( atlas_origin, dim, @@ -99,14 +142,14 @@ where |atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm), )); }, - make_face_texel: |vol: &mut V, pos, light, _, _| { - let cell = vol.get(pos).ok(); - let (glowy, shiny) = cell - .map(|c| (c.is_glowy(), c.is_shiny())) - .unwrap_or_default(); - let col = cell - .and_then(|vox| vox.get_color()) - .unwrap_or_else(Rgb::zero); + make_face_texel: #[inline(always)] move |flat: &mut _, pos, light, _, _| { + let cell = match flat_get(flat, pos) { + Cell::Filled(c) => c, + _ => unreachable!("Face texels cannot be empty"), + }; + let glowy = cell.is_glowy(); + let shiny = cell.is_shiny(); + let col = cell.col; TerrainVertex::make_col_light_figure(light, glowy, shiny, col) }, }); @@ -162,30 +205,44 @@ where ); let (flat, flat_get) = { - let (w, h, d) = (greedy_size + 2).into_tuple(); + let (w_, h_, d_) = greedy_size.into_tuple(); + let (w, h, d) = (w_ + 2, h_ + 2, d_ + 2); + let wh = w * h; let flat = { - let mut flat = vec![Cell::empty(); (w * h * d) as usize]; - let mut i = 0; - for x in -1..greedy_size.x + 1 { + let mut flat_ = vec![Cell::empty(); (d * wh) as usize]; + let flat = &mut flat_[0..(d * wh) as usize]; + // NOTE: We can skip the outside edges because we know they're already empty. + flat.chunks_exact_mut(wh as usize).skip(1).take(d_ as usize).enumerate().for_each(|(z, flat)| { + let z = z as i32; + flat.chunks_exact_mut(w as usize).skip(1).take(h_ as usize).enumerate().for_each(|(y, flat)| { + let y = y as i32; + flat.into_iter().skip(1).take(w_ as usize).enumerate().for_each(|(x, flat)| { + let x = x as i32; + *flat = vol.get(Vec3::new(x, y, z)).copied().unwrap_or_else(|_| Cell::empty()); + }); + }); + }); + /* for z in -1..greedy_size.z + 1 { for y in -1..greedy_size.y + 1 { - for z in -1..greedy_size.z + 1 { + for x in -1..greedy_size.x + 1 { let wpos = lower_bound + Vec3::new(x, y, z); let block = vol.get(wpos).map(|b| *b).unwrap_or_else(|_| Cell::empty()); flat[i] = block; i += 1; } } - } - flat + } */ + flat_ }; - let flat_get = move |flat: &Vec, Vec3 { x, y, z }| match flat - .get((x * h * d + y * d + z) as usize) + let wh = w * h; + let flat_get = #[inline(always)] move |flat: &Vec, Vec3 { x, y, z }| /* match flat + .get((x * hd + y * d + z) as usize) .copied() { Some(b) => b, None => panic!("x {} y {} z {} d {} h {}", x, y, z, d, h), - }; + }*/flat[(z * wh + y * w + x) as usize]; (flat, flat_get) }; @@ -197,25 +254,25 @@ where let greedy_size_cross = greedy_size; let draw_delta = Vec3::new(1, 1, 1); - let get_light = move |flat: &mut _, pos: Vec3| { + let get_light = #[inline(always)] move |flat: &mut _, pos: Vec3| { if flat_get(flat, pos).is_empty() { 1.0 } else { 0.0 } }; - let get_glow = |_flat: &mut _, _pos: Vec3| 0.0; - let get_color = move |flat: &mut _, pos: Vec3| { + let get_glow = #[inline(always)] |_flat: &mut _, _pos: Vec3| 0.0; + let get_color = #[inline(always)] move |flat: &mut _, pos: Vec3| { flat_get(flat, pos).get_color().unwrap_or_else(Rgb::zero) }; - let get_opacity = move |flat: &mut _, pos: Vec3| flat_get(flat, pos).is_empty(); - let should_draw = move |flat: &mut _, pos: Vec3, from: Cell, to: Cell, /*delta: Vec3, */uv| { + let get_opacity = #[inline(always)] move |flat: &mut _, pos: Vec3| flat_get(flat, pos).is_empty(); + let should_draw = #[inline(always)] move |_flat: &mut _, pos: Vec3, from: Cell, to: Cell, /*delta: Vec3, */uv| { should_draw_greedy_ao(vertical_stripes, pos, from, to,/* delta, */uv/* , |vox| flat_get(flat, vox) */) }; // NOTE: Fits in i16 (much lower actually) so f32 is no problem (and the final // position, pos + mesh_delta, is guaranteed to fit in an f32). let mesh_delta = lower_bound.as_::(); - let create_opaque = |atlas_pos, pos: Vec3, norm, _meta| { + let create_opaque = #[inline(always)] |atlas_pos, pos: Vec3, norm, _meta| { SpriteVertex::new(atlas_pos, pos + mesh_delta, norm) }; @@ -224,13 +281,13 @@ where draw_delta, greedy_size, greedy_size_cross, - get_vox: move |flat: &mut _, vox| flat_get(flat, vox), - get_ao: |_: &mut _, _: Vec3| 1.0, + get_vox: #[inline(always)] move |flat: &mut _, vox| flat_get(flat, vox), + get_ao: #[inline(always)] |_: &mut _, _: Vec3| 1.0, get_light, get_glow, get_opacity, should_draw, - push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &bool| { + push_quad: #[inline(always)] |atlas_origin, dim, origin, draw_dim, norm, meta: &bool| { opaque_mesh.push_quad(greedy::create_quad( atlas_origin, dim, @@ -241,7 +298,7 @@ where |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), )); }, - make_face_texel: move |flat: &mut _, pos, light, glow, ao| { + make_face_texel: #[inline(always)] move |flat: &mut _, pos, light, glow, ao| { TerrainVertex::make_col_light(light, glow, get_color(flat, pos), ao) }, }); @@ -283,29 +340,29 @@ where let greedy_size_cross = greedy_size; let draw_delta = lower_bound; - let get_light = |vol: &mut V, pos: Vec3| { + let get_light = #[inline(always)] |vol: &mut V, pos: Vec3| { if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) { 1.0 } else { 0.0 } }; - let get_glow = |_vol: &mut V, _pos: Vec3| 0.0; - let get_color = |vol: &mut V, pos: Vec3| { + let get_glow = #[inline(always)] |_vol: &mut V, _pos: Vec3| 0.0; + let get_color = #[inline(always)] |vol: &mut V, pos: Vec3| { vol.get(pos) .ok() .and_then(|vox| vox.get_color()) .unwrap_or_else(Rgb::zero) }; - let get_opacity = |vol: &mut V, pos: Vec3| vol.get(pos).map_or(true, |vox| vox.is_empty()); - let should_draw = |vol: &mut V, pos: Vec3, from: Cell, to: Cell, /*delta: Vec3, */uv| { + let get_opacity = #[inline(always)] |vol: &mut V, pos: Vec3| vol.get(pos).map_or(true, |vox| vox.is_empty()); + let should_draw = #[inline(always)] |vol: &mut V, pos: Vec3, from: Cell, to: Cell, /*delta: Vec3, */uv| { should_draw_greedy(pos, from, to,/* delta, */uv/*, |vox| { vol.get(vox) .map(|vox| *vox) .unwrap_or_else(|_| Cell::empty()) }*/) }; - let create_opaque = |_atlas_pos, pos: Vec3, norm| ParticleVertex::new(pos, norm); + let create_opaque = #[inline(always)] |_atlas_pos, pos: Vec3, norm| ParticleVertex::new(pos, norm); let mut opaque_mesh = Mesh::new(); greedy.push(GreedyConfig { @@ -313,17 +370,17 @@ where draw_delta, greedy_size, greedy_size_cross, - get_vox: |vol: &mut V, vox| { + get_vox: #[inline(always)] |vol: &mut V, vox| { vol.get(vox) .map(|vox| *vox) .unwrap_or_else(|_| Cell::empty()) }, - get_ao: |_: &mut V, _: Vec3| 1.0, + get_ao: #[inline(always)] |_: &mut V, _: Vec3| 1.0, get_light, get_glow, get_opacity, should_draw, - push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| { + push_quad: #[inline(always)] |atlas_origin, dim, origin, draw_dim, norm, meta: &()| { opaque_mesh.push_quad(greedy::create_quad( atlas_origin, dim, @@ -334,7 +391,7 @@ where |atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm), )); }, - make_face_texel: move |vol: &mut V, pos, light, glow, ao| { + make_face_texel: #[inline(always)] move |vol: &mut V, pos, light, glow, ao| { TerrainVertex::make_col_light(light, glow, get_color(vol, pos), ao) }, }); diff --git a/world/src/layer/tree.rs b/world/src/layer/tree.rs index 39e6342aa0..38d7d1c430 100644 --- a/world/src/layer/tree.rs +++ b/world/src/layer/tree.rs @@ -16,6 +16,7 @@ use common::{ }, vol::ReadVol, }; +use common_base::prof_span; use lazy_static::lazy_static; use probability::{ prelude::{source, Gaussian, Inverse}, @@ -113,6 +114,7 @@ pub fn apply_trees_to( dynamic_rng: &mut impl Rng, /* calendar: Option<&Calendar>, */ ) { + prof_span!("apply_trees_to"); // TODO: Get rid of this #[allow(clippy::large_enum_variant)] enum TreeModel { diff --git a/world/src/site2/gen.rs b/world/src/site2/gen.rs index 5a02abbb3c..e22fb54c00 100644 --- a/world/src/site2/gen.rs +++ b/world/src/site2/gen.rs @@ -16,6 +16,7 @@ use common::{ }, vol::ReadVol, }; +use common_base::prof_span; use fxhash::FxHasher64; use hashbrown::{/*hash_map::Entry, */HashMap}; use noisy_float::types::n32; @@ -2858,8 +2859,8 @@ impl Painter<'_> { let aabb = Self::get_bounds(cache, tree, prim); /*if !(aabb.size().w > 8 || aabb.size().h > 8 || aabb.size().d > 16) */{ let mut do_segment = || { - let distance = segment.end - segment.start; - let distance_proj = distance / distance.magnitude_squared(); + let distance = segment.start - segment.end; + let distance_proj = -distance / distance.magnitude_squared(); let segment_start = segment.start - 0.5; if r0 == r1 { let radius_2 = r0 * r0; @@ -2873,7 +2874,7 @@ impl Painter<'_> { let pos = pos.as_::(); let length = pos - segment_start; let t = length.dot(distance_proj).clamped(0.0, 1.0); - let diff = distance * t - length; + let diff = distance * t + length; diff.magnitude_squared() < radius_2 }, hit, @@ -2888,7 +2889,7 @@ impl Painter<'_> { let pos = pos.as_::(); let length = pos - segment_start; let t = length.dot(distance_proj).clamped(0.0, 1.0); - let mut diff = distance * t - length; + let mut diff = distance * t + length; diff.z *= z_scale; diff.magnitude_squared() < radius_2 }, @@ -2905,7 +2906,7 @@ impl Painter<'_> { let pos = pos.as_::(); let length = pos - segment_start; let t = length.dot(distance_proj).clamped(0.0, 1.0); - let diff = distance * t - length; + let diff = distance * t + length; let radius = Lerp::lerp_unclamped(r0, r1, t); diff.magnitude_squared() < radius * radius }, @@ -2921,7 +2922,7 @@ impl Painter<'_> { let pos = pos.as_::(); let length = pos - segment_start; let t = length.dot(distance_proj).clamped(0.0, 1.0); - let mut diff = distance * t - length; + let mut diff = distance * t + length; diff.z *= z_scale; let radius = Lerp::lerp_unclamped(r0, r1, t); diff.magnitude_squared() < radius * radius @@ -5698,6 +5699,7 @@ pub fn render_collect<'b, 'c, F: Filler + 'c, Render: FnOnce(&Painter<'b>, &mut fill.sample_at(arena, &mut bounds_cache, prim, prim_tree, render_area, &info, filler) }; */ + prof_span!("render"); render(&painter, &mut fill_fn); /* ( painter.prims.into_inner(),