From 25de2d1819408fbb9310bffb2379606997ecbfc6 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sat, 26 Jun 2021 15:35:07 -0700 Subject: [PATCH] Port Mesh to RenderAsset, add Slab and FrameSlabMap garbage collection for Bind Groups --- crates/bevy_utils/src/lib.rs | 3 +- crates/bevy_utils/src/slab.rs | 214 ++++++++ examples/tools/bevymark_pipelined.rs | 4 +- pipelined/bevy_pbr2/src/lib.rs | 1 - pipelined/bevy_pbr2/src/material.rs | 11 +- pipelined/bevy_pbr2/src/render/light.rs | 16 +- pipelined/bevy_pbr2/src/render/mod.rs | 119 ++--- .../bevy_render2/src/core_pipeline/mod.rs | 4 +- .../src/mesh/mesh/mesh_resource_provider.rs | 69 --- .../src/mesh/{mesh.rs => mesh/mod.rs} | 478 ++++++++++-------- pipelined/bevy_render2/src/mesh/mod.rs | 12 +- pipelined/bevy_render2/src/render_asset.rs | 9 +- pipelined/bevy_render2/src/texture/image.rs | 1 - .../bevy_render2/src/texture/texture_cache.rs | 13 +- pipelined/bevy_render2/src/view/window.rs | 9 +- pipelined/bevy_sprite2/src/render/mod.rs | 46 +- 16 files changed, 591 insertions(+), 418 deletions(-) create mode 100644 crates/bevy_utils/src/slab.rs delete mode 100644 pipelined/bevy_render2/src/mesh/mesh/mesh_resource_provider.rs rename pipelined/bevy_render2/src/mesh/{mesh.rs => mesh/mod.rs} (93%) diff --git a/crates/bevy_utils/src/lib.rs b/crates/bevy_utils/src/lib.rs index c3b78781d3..57202de29b 100644 --- a/crates/bevy_utils/src/lib.rs +++ b/crates/bevy_utils/src/lib.rs @@ -1,7 +1,8 @@ mod enum_variant_meta; -pub use enum_variant_meta::*; +pub mod slab; pub use ahash::AHasher; +pub use enum_variant_meta::*; pub use instant::{Duration, Instant}; pub use tracing; pub use uuid::Uuid; diff --git a/crates/bevy_utils/src/slab.rs b/crates/bevy_utils/src/slab.rs new file mode 100644 index 0000000000..374286918a --- /dev/null +++ b/crates/bevy_utils/src/slab.rs @@ -0,0 +1,214 @@ +use std::{ + marker::PhantomData, + ops::{Index, IndexMut}, +}; + +use crate::HashMap; + +#[derive(Debug)] +pub struct SlabKey { + index: usize, + marker: PhantomData, +} + +impl Copy for SlabKey {} + +impl Clone for SlabKey { + fn clone(&self) -> Self { + Self { + index: self.index, + marker: PhantomData, + } + } +} + +impl SlabKey { + #[inline] + pub fn index(&self) -> usize { + self.index + } +} + +pub struct Slab { + values: Vec>, + empty_indices: Vec, +} + +impl Default for Slab { + fn default() -> Self { + Self { + values: Default::default(), + empty_indices: Default::default(), + } + } +} + +impl Slab { + pub fn get(&self, key: SlabKey) -> Option<&V> { + self.values[key.index].as_ref() + } + + pub fn get_mut(&mut self, key: SlabKey) -> Option<&mut V> { + self.values[key.index].as_mut() + } + + pub fn add(&mut self, value: V) -> SlabKey { + let index = if let Some(index) = self.empty_indices.pop() { + self.values[index] = Some(value); + index + } else { + let index = self.values.len(); + self.values.push(Some(value)); + index + }; + SlabKey { + index, + marker: PhantomData, + } + } + + pub fn remove(&mut self, key: SlabKey) -> Option { + if let Some(value) = self.values[key.index].take() { + self.empty_indices.push(key.index); + Some(value) + } else { + None + } + } + + pub fn iter(&self) -> impl Iterator { + self.values.iter().filter_map(|v| v.as_ref()) + } + + /// Retains any items matching the given predicate. Removed items will be dropped and their indices will be + /// made available for future items. + pub fn retain_in_place(&mut self, mut predicate: impl FnMut(&mut V) -> bool) { + for (i, value) in self.values.iter_mut().enumerate() { + if let Some(value) = value { + if predicate(value) { + continue; + } + } else { + continue; + } + + *value = None; + self.empty_indices.push(i); + } + } +} + +impl Index> for Slab { + type Output = V; + + #[inline] + fn index(&self, index: SlabKey) -> &Self::Output { + self.get(index).unwrap() + } +} + +impl IndexMut> for Slab { + #[inline] + fn index_mut(&mut self, index: SlabKey) -> &mut Self::Output { + self.get_mut(index).unwrap() + } +} + +pub struct FrameSlabMapValue { + value: V, + key: K, + frames_since_last_use: usize, +} + +pub struct FrameSlabMap { + slab: Slab>, + keys: HashMap>, +} + +impl Default for FrameSlabMap { + fn default() -> Self { + Self { + slab: Default::default(), + keys: Default::default(), + } + } +} + +pub type FrameSlabMapKey = SlabKey>; + +impl FrameSlabMap { + pub fn get_value(&self, slab_key: FrameSlabMapKey) -> Option<&V> { + let value = self.slab.get(slab_key)?; + Some(&value.value) + } + + pub fn get_value_mut(&mut self, slab_key: FrameSlabMapKey) -> Option<&mut V> { + let value = self.slab.get_mut(slab_key)?; + Some(&mut value.value) + } + + pub fn get_or_insert_with( + &mut self, + key: K, + f: impl FnOnce() -> V, + ) -> SlabKey> { + match self.keys.entry(key.clone()) { + std::collections::hash_map::Entry::Occupied(mut entry) => { + let slab_key = *entry.get(); + match self.slab.get_mut(slab_key) { + Some(value) => { + value.frames_since_last_use = 0; + slab_key + } + None => { + let key = self.slab.add(FrameSlabMapValue { + frames_since_last_use: 0, + value: f(), + key, + }); + entry.insert(key); + key + } + } + } + std::collections::hash_map::Entry::Vacant(entry) => { + let key = self.slab.add(FrameSlabMapValue { + frames_since_last_use: 0, + value: f(), + key, + }); + entry.insert(key); + key + } + } + } + + pub fn next_frame(&mut self) { + let keys = &mut self.keys; + self.slab.retain_in_place(|v| { + v.frames_since_last_use += 1; + if v.frames_since_last_use < 3 { + true + } else { + keys.remove(&v.key); + false + } + }) + } +} + +impl Index> for FrameSlabMap { + type Output = V; + + #[inline] + fn index(&self, index: FrameSlabMapKey) -> &Self::Output { + self.get_value(index).unwrap() + } +} + +impl IndexMut> for FrameSlabMap { + #[inline] + fn index_mut(&mut self, index: FrameSlabMapKey) -> &mut Self::Output { + self.get_value_mut(index).unwrap() + } +} diff --git a/examples/tools/bevymark_pipelined.rs b/examples/tools/bevymark_pipelined.rs index a8bb640ae5..4789853fe3 100644 --- a/examples/tools/bevymark_pipelined.rs +++ b/examples/tools/bevymark_pipelined.rs @@ -242,7 +242,7 @@ impl Default for CountTimer { fn counter_system( mut timer: Local, - diagnostics: Res, + _diagnostics: Res, time: Res