Skip to content

Commit

Permalink
Shrink Resources
Browse files Browse the repository at this point in the history
  • Loading branch information
james7132 committed Jun 7, 2022
1 parent 56aa9d5 commit d8758f8
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 29 deletions.
46 changes: 31 additions & 15 deletions crates/bevy_ecs/src/storage/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ use crate::storage::{Column, SparseSet};
use bevy_ptr::{OwningPtr, Ptr, PtrMut, UnsafeCellDeref};
use std::cell::UnsafeCell;

pub(crate) struct ResourceInfo {
pub data: Column,
pub component_info: ArchetypeComponentInfo,
}

/// The backing store for all [`Resource`]s stored in the [`World`].
///
/// [`Resource`]: crate::system::Resource
/// [`World`]: crate::world::World
#[derive(Default)]
pub struct Resources {
pub(crate) resources: SparseSet<ComponentId, Column>,
pub(crate) components: SparseSet<ComponentId, ArchetypeComponentInfo>,
pub(crate) resources: SparseSet<ComponentId, ResourceInfo>,
}

impl Resources {
Expand All @@ -22,9 +26,9 @@ impl Resources {
&self,
component_id: ComponentId,
) -> Option<ArchetypeComponentId> {
self.components
self.resources
.get(component_id)
.map(|info| info.archetype_component_id)
.map(|info| info.component_info.archetype_component_id)
}

/// The total number of resoruces stored in the [`World`]
Expand All @@ -44,35 +48,39 @@ impl Resources {
self.resources.is_empty()
}

/// Gets a read-only [`Ptr`] to a resource, if available.
#[inline]
pub fn get(&self, component_id: ComponentId) -> Option<Ptr<'_>> {
let column = self.resources.get(component_id)?;
let column = &self.resources.get(component_id)?.data;
// SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of the
// ptr value / drop is called when R is dropped
(!column.is_empty()).then(|| unsafe { column.get_data_unchecked(0) })
}

/// Gets a read-only [`Ptr`] to a resource, if available.
#[inline]
pub fn get_mut(&mut self, component_id: ComponentId) -> Option<PtrMut<'_>> {
let column = self.resources.get_mut(component_id)?;
let column = &mut self.resources.get_mut(component_id)?.data;
// SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of the
// ptr value / drop is called when R is dropped
(!column.is_empty()).then(|| unsafe { column.get_data_unchecked_mut(0) })
}

/// Gets the [`ComponentTicks`] to a resource, if available.
#[inline]
pub fn get_ticks(&self, component_id: ComponentId) -> Option<&ComponentTicks> {
let column = self.resources.get(component_id)?;
let column = &self.resources.get(component_id)?.data;
// SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of the
// ptr value / drop is called when R is dropped
(!column.is_empty()).then(|| unsafe { column.get_ticks_unchecked(0).deref() })
}

/// Checks if the a resource is currently stored with a given ID.
#[inline]
pub fn contains(&self, component_id: ComponentId) -> bool {
self.resources
.get(component_id)
.map(|column| !column.is_empty())
.map(|info| !info.data.is_empty())
.unwrap_or(false)
}

Expand All @@ -81,32 +89,40 @@ impl Resources {
&self,
component_id: ComponentId,
) -> Option<(Ptr<'_>, &UnsafeCell<ComponentTicks>)> {
let column = self.resources.get(component_id)?;
let column = &self.resources.get(component_id)?.data;
// SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of the
// ptr value / drop is called when R is dropped
(!column.is_empty())
.then(|| unsafe { (column.get_data_unchecked(0), column.get_ticks_unchecked(0)) })
}

/// Inserts a resource into the world.
///
/// # Safety
/// - ptr must point to valid data of this column's component type
/// ptr must point to valid data of this column's component type which
/// must correspond to the provided ID.
#[inline]
pub unsafe fn insert(
&mut self,
component_id: ComponentId,
data: OwningPtr<'_>,
ticks: ComponentTicks,
) -> Option<()> {
let column = self.resources.get_mut(component_id)?;
let column = &mut self.resources.get_mut(component_id)?.data;
debug_assert!(column.is_empty());
column.push(data, ticks);
Some(())
}

/// Removes a resource from the world.
///
/// # Safety
/// ptr must point to valid data of this column's component type which
/// must correspond to the provided ID.
#[inline]
#[must_use = "The returned pointer to the removed component should be used or dropped"]
pub fn remove(&mut self, component_id: ComponentId) -> Option<(OwningPtr<'_>, ComponentTicks)> {
let column = self.resources.get_mut(component_id)?;
let column = &mut self.resources.get_mut(component_id)?.data;
if column.is_empty() {
return None;
}
Expand All @@ -117,7 +133,7 @@ impl Resources {

#[inline]
pub(crate) fn remove_and_drop(&mut self, component_id: ComponentId) -> Option<()> {
let column = self.resources.get_mut(component_id)?;
let column = &mut self.resources.get_mut(component_id)?.data;
if column.is_empty() {
return None;
}
Expand All @@ -130,8 +146,8 @@ impl Resources {
}

pub fn check_change_ticks(&mut self, change_tick: u32) {
for column in self.resources.values_mut() {
column.check_change_ticks(change_tick);
for info in self.resources.values_mut() {
info.data.check_change_ticks(change_tick);
}
}
}
31 changes: 17 additions & 14 deletions crates/bevy_ecs/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
},
entity::{AllocAtWithoutReplacement, Entities, Entity},
query::{QueryState, WorldQuery},
storage::{Column, SparseSet, Storages},
storage::{Column, ResourceInfo, SparseSet, Storages},
system::Resource,
};
use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref};
Expand Down Expand Up @@ -1195,22 +1195,25 @@ impl World {
unsafe fn initialize_resource_internal(&mut self, component_id: ComponentId) -> &mut Column {
// SAFE: resource archetype always exists
let resources = &mut self.storages.resources;
let resource_components = &mut resources.components;
let resources = &mut resources.resources;
let archetype_component_count = &mut self.archetypes.archetype_component_count;
let components = &self.components;
resources.get_or_insert_with(component_id, || {
resource_components.insert(
component_id,
ArchetypeComponentInfo {
archetype_component_id: ArchetypeComponentId::new(*archetype_component_count),
storage_type: StorageType::Table,
},
);
*archetype_component_count += 1;
let component_info = components.get_info_unchecked(component_id);
Column::with_capacity(component_info, 1)
})
&mut resources
.get_or_insert_with(component_id, || {
let component_info = components.get_info_unchecked(component_id);
let info = ResourceInfo {
data: Column::with_capacity(component_info, 1),
component_info: ArchetypeComponentInfo {
archetype_component_id: ArchetypeComponentId::new(
*archetype_component_count,
),
storage_type: StorageType::Table,
},
};
*archetype_component_count += 1;
info
})
.data
}

pub(crate) fn initialize_resource<R: Resource>(&mut self) -> ComponentId {
Expand Down

0 comments on commit d8758f8

Please sign in to comment.