-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
[Merged by Bors] - Extract Resources into their own dedicated storage #4809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
7cd3e3f
Preliminary changes
james7132 76ede2f
Fix compilation
james7132 b7b16be
Provide internal helper function
james7132 5464d47
More complete Resources impl
james7132 32c5456
Fix build
james7132 bb9a49f
Cleanup
james7132 b719c1b
Fix CI
james7132 99f14d7
Fix CI
james7132 4918e10
Shrink Resources
james7132 2b24bac
Less jank way of fetching ticks.
james7132 ab675d1
Better safety comment.
james7132 bd25ccc
Better safety comment.
james7132 70578fe
Correct safety comment pointing to the right parameter.
james7132 27ce1a3
Much simpler remove impl.
james7132 520fd30
Update safety comments
james7132 7737705
Move the unsafe into Column
james7132 a6b5e4b
Column::get
james7132 610c617
Formatting
james7132 e32ec9e
Address World review comments
james7132 515e2b3
Make storage APIs a bit more externally friendly
james7132 c1f1133
Remove contains
james7132 850b318
Merge branch 'main' into no-unique-components
james7132 a0731e6
Merge branch 'main' into no-unique-components
james7132 f4123b9
Fix test compilation
james7132 bb38531
Fix must_use typo
james7132 bb59857
Change panic message.
james7132 3556580
ResourceInfo -> ResourceData
james7132 734584d
Type doc comment for ResourceData
james7132 01c176f
Merge branch 'main' into no-unique-components
james7132 58027c4
Fix CI
james7132 d3d846a
Update get's doc comment.
james7132 40afd47
Update get_mut's doc comment.
james7132 7b9fbf0
Fix docs typo
james7132 a6c8977
Use an impl param instead of a bound
james7132 39be822
ArchetypeComponentInfo -> Id
james7132 efd5113
Remove public access to data methods
james7132 535bc9f
Update safety comments on mutative resource APIs
james7132 7932fa8
Fix CI
james7132 c2476ed
Update safety docs on get_ticks
james7132 31cd2b4
Formatting
james7132 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
use crate::archetype::ArchetypeComponentId; | ||
use crate::component::{ComponentId, ComponentTicks, Components}; | ||
use crate::storage::{Column, SparseSet}; | ||
use bevy_ptr::{OwningPtr, Ptr, UnsafeCellDeref}; | ||
use std::cell::UnsafeCell; | ||
|
||
/// The type-erased backing storage and metadata for a single resource within a [`World`]. | ||
/// | ||
/// [`World`]: crate::world::World | ||
pub struct ResourceData { | ||
column: Column, | ||
james7132 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
id: ArchetypeComponentId, | ||
} | ||
|
||
impl ResourceData { | ||
/// Returns true if the resource is populated. | ||
#[inline] | ||
pub fn is_present(&self) -> bool { | ||
!self.column.is_empty() | ||
} | ||
|
||
/// Gets the [`ArchetypeComponentId`] for the resource. | ||
#[inline] | ||
pub fn id(&self) -> ArchetypeComponentId { | ||
self.id | ||
} | ||
|
||
/// Gets a read-only pointer to the underlying resource, if available. | ||
#[inline] | ||
pub fn get_data(&self) -> Option<Ptr<'_>> { | ||
self.column.get_data(0) | ||
} | ||
|
||
/// Gets a read-only reference to the change ticks of the underlying resource, if available. | ||
#[inline] | ||
pub fn get_ticks(&self) -> Option<&ComponentTicks> { | ||
self.column | ||
.get_ticks(0) | ||
// SAFETY: | ||
// - This borrow's lifetime is bounded by the lifetime on self. | ||
// - A read-only borrow on self can only exist while a mutable borrow doesn't | ||
// exist. | ||
.map(|ticks| unsafe { ticks.deref() }) | ||
} | ||
|
||
#[inline] | ||
pub(crate) fn get_with_ticks(&self) -> Option<(Ptr<'_>, &UnsafeCell<ComponentTicks>)> { | ||
james7132 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.column.get(0) | ||
} | ||
|
||
/// Inserts a value into the resource. If a value is already present | ||
/// it will be replaced. | ||
/// | ||
/// # Safety | ||
/// `value` must be valid for the underlying type for the resource. | ||
/// | ||
/// The underlying type must be [`Send`] or be inserted from the main thread. | ||
/// This can be validated with [`World::validate_non_send_access_untyped`]. | ||
/// | ||
/// [`World::validate_non_send_access_untyped`]: crate::world::World::validate_non_send_access_untyped | ||
#[inline] | ||
pub(crate) unsafe fn insert(&mut self, value: OwningPtr<'_>, change_tick: u32) { | ||
if self.is_present() { | ||
self.column.replace(0, value, change_tick); | ||
} else { | ||
self.column.push(value, ComponentTicks::new(change_tick)); | ||
} | ||
} | ||
|
||
/// Inserts a value into the resource with a pre-existing change tick. If a | ||
/// value is already present it will be replaced. | ||
/// | ||
/// # Safety | ||
/// `value` must be valid for the underlying type for the resource. | ||
/// | ||
/// The underlying type must be [`Send`] or be inserted from the main thread. | ||
/// This can be validated with [`World::validate_non_send_access_untyped`]. | ||
/// | ||
/// [`World::validate_non_send_access_untyped`]: crate::world::World::validate_non_send_access_untyped | ||
#[inline] | ||
pub(crate) unsafe fn insert_with_ticks( | ||
james7132 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
&mut self, | ||
james7132 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
value: OwningPtr<'_>, | ||
change_ticks: ComponentTicks, | ||
) { | ||
if self.is_present() { | ||
self.column.replace_untracked(0, value); | ||
*self.column.get_ticks_unchecked(0).deref_mut() = change_ticks; | ||
} else { | ||
self.column.push(value, change_ticks); | ||
} | ||
} | ||
|
||
/// Removes a value from the resource, if present. | ||
/// | ||
/// # Safety | ||
/// The underlying type must be [`Send`] or be removed from the main thread. | ||
/// This can be validated with [`World::validate_non_send_access_untyped`]. | ||
/// | ||
/// The removed value must be used or dropped. | ||
/// | ||
/// [`World::validate_non_send_access_untyped`]: crate::world::World::validate_non_send_access_untyped | ||
#[inline] | ||
#[must_use = "The returned pointer to the removed component should be used or dropped"] | ||
pub(crate) unsafe fn remove(&mut self) -> Option<(OwningPtr<'_>, ComponentTicks)> { | ||
self.column.swap_remove_and_forget(0) | ||
} | ||
|
||
/// Removes a value from the resource, if present, and drops it. | ||
/// | ||
/// # Safety | ||
/// The underlying type must be [`Send`] or be removed from the main thread. | ||
/// This can be validated with [`World::validate_non_send_access_untyped`]. | ||
/// | ||
/// [`World::validate_non_send_access_untyped`]: crate::world::World::validate_non_send_access_untyped | ||
#[inline] | ||
pub(crate) unsafe fn remove_and_drop(&mut self) { | ||
self.column.clear(); | ||
james7132 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
/// The backing store for all [`Resource`]s stored in the [`World`]. | ||
/// | ||
/// [`Resource`]: crate::system::Resource | ||
/// [`World`]: crate::world::World | ||
#[derive(Default)] | ||
pub struct Resources { | ||
resources: SparseSet<ComponentId, ResourceData>, | ||
} | ||
|
||
impl Resources { | ||
/// The total number of resources stored in the [`World`] | ||
/// | ||
/// [`World`]: crate::world::World | ||
#[inline] | ||
pub fn len(&self) -> usize { | ||
self.resources.len() | ||
} | ||
|
||
/// Returns true if there are no resources stored in the [`World`], | ||
/// false otherwise. | ||
/// | ||
/// [`World`]: crate::world::World | ||
#[inline] | ||
pub fn is_empty(&self) -> bool { | ||
self.resources.is_empty() | ||
} | ||
|
||
/// Gets read-only access to a resource, if it exists. | ||
#[inline] | ||
pub fn get(&self, component_id: ComponentId) -> Option<&ResourceData> { | ||
self.resources.get(component_id) | ||
} | ||
|
||
/// Gets mutable access to a resource, if it exists. | ||
#[inline] | ||
pub(crate) fn get_mut(&mut self, component_id: ComponentId) -> Option<&mut ResourceData> { | ||
self.resources.get_mut(component_id) | ||
} | ||
|
||
/// Fetches or initializes a new resource and returns back it's underlying column. | ||
/// | ||
/// # Panics | ||
/// Will panic if `component_id` is not valid for the provided `components` | ||
pub(crate) fn initialize_with( | ||
&mut self, | ||
component_id: ComponentId, | ||
components: &Components, | ||
f: impl FnOnce() -> ArchetypeComponentId, | ||
) -> &mut ResourceData { | ||
self.resources.get_or_insert_with(component_id, || { | ||
let component_info = components.get_info(component_id).unwrap(); | ||
ResourceData { | ||
column: Column::with_capacity(component_info, 1), | ||
id: f(), | ||
} | ||
}) | ||
} | ||
|
||
pub(crate) fn check_change_ticks(&mut self, change_tick: u32) { | ||
for info in self.resources.values_mut() { | ||
info.column.check_change_ticks(change_tick); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.