Skip to content

Commit 7f528bd

Browse files
resource storage
1 parent fda7daa commit 7f528bd

24 files changed

Lines changed: 968 additions & 369 deletions

File tree

benches/benches/bevy_ecs/resources.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fn create_world() -> World {
1919
let resource_id =
2020
world.register_component_with_descriptor(ComponentDescriptor::new_with_layout(
2121
"",
22-
StorageType::SparseSet,
22+
StorageType::Resource,
2323
Layout::new::<()>(),
2424
None,
2525
true,

crates/bevy_ecs/macros/src/component.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub fn derive_resource(input: TokenStream) -> TokenStream {
4747
}
4848
});
4949

50-
let storage = storage_path(&bevy_ecs_path, StorageTy::Table);
50+
let storage = storage_path(&bevy_ecs_path, StorageTy::Resource);
5151

5252
ast.generics
5353
.make_where_clause()
@@ -554,6 +554,7 @@ struct Attrs {
554554
enum StorageTy {
555555
Table,
556556
SparseSet,
557+
Resource,
557558
}
558559

559560
struct Require {
@@ -747,6 +748,7 @@ fn storage_path(bevy_ecs_path: &Path, ty: StorageTy) -> TokenStream2 {
747748
let storage_type = match ty {
748749
StorageTy::Table => Ident::new("Table", Span::call_site()),
749750
StorageTy::SparseSet => Ident::new("SparseSet", Span::call_site()),
751+
StorageTy::Resource => Ident::new("Resource", Span::call_site()),
750752
};
751753

752754
quote! { #bevy_ecs_path::component::StorageType::#storage_type }

crates/bevy_ecs/src/archetype.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ pub struct Archetype {
390390
}
391391

392392
impl Archetype {
393-
/// `table_components` and `sparse_set_components` must be sorted
393+
/// `table_components` must be sorted
394394
pub(crate) fn new(
395395
components: &Components,
396396
component_index: &mut ComponentIndex,
@@ -399,6 +399,7 @@ impl Archetype {
399399
table_id: TableId,
400400
table_components: impl Iterator<Item = ComponentId>,
401401
sparse_set_components: impl Iterator<Item = ComponentId>,
402+
resource_components: impl Iterator<Item = ComponentId>,
402403
) -> Self {
403404
let (min_table, _) = table_components.size_hint();
404405
let (min_sparse, _) = sparse_set_components.size_hint();
@@ -424,22 +425,23 @@ impl Archetype {
424425
.insert(id, ArchetypeRecord { column: Some(idx) });
425426
}
426427

427-
for component_id in sparse_set_components {
428+
for component_id in sparse_set_components.chain(resource_components) {
428429
// SAFETY: We are creating an archetype that includes this component so it must exist
429430
let info = unsafe { components.get_info_unchecked(component_id) };
430431
info.update_archetype_flags(&mut flags);
431432
observers.update_archetype_flags(component_id, &mut flags);
432433
archetype_components.insert(
433434
component_id,
434435
ArchetypeComponentInfo {
435-
storage_type: StorageType::SparseSet,
436+
storage_type: info.storage_type(),
436437
},
437438
);
438439
component_index
439440
.entry(component_id)
440441
.or_default()
441442
.insert(id, ArchetypeRecord { column: None });
442443
}
444+
443445
Self {
444446
id,
445447
table_id,
@@ -523,6 +525,19 @@ impl Archetype {
523525
.map(|(id, _)| *id)
524526
}
525527

528+
/// Gets an iterator of all of the components stored in [`ResourceStorages`].
529+
///
530+
/// All of the IDs are unique.
531+
///
532+
/// [`ResourceStorages`]: crate::storage::ResourceStorages
533+
#[inline]
534+
pub fn resource_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
535+
self.components
536+
.iter()
537+
.filter(|(_, component)| component.storage_type == StorageType::Resource)
538+
.map(|(id, _)| *id)
539+
}
540+
526541
/// Returns a slice of all of the components in the archetype.
527542
///
528543
/// All of the IDs are unique.
@@ -754,10 +769,13 @@ impl ArchetypeGeneration {
754769
}
755770
}
756771

772+
/// Components must be sorted
773+
/// (which allows `ArchetypeComponents` to be used as an archetype's identity).
757774
#[derive(Hash, PartialEq, Eq)]
758775
struct ArchetypeComponents {
759776
table_components: Box<[ComponentId]>,
760777
sparse_set_components: Box<[ComponentId]>,
778+
resource_components: Box<[ComponentId]>,
761779
}
762780

763781
/// Maps a [`ComponentId`] to the list of [`Archetypes`]([`Archetype`]) that contain the [`Component`](crate::component::Component),
@@ -804,6 +822,7 @@ impl Archetypes {
804822
TableId::empty(),
805823
Vec::new(),
806824
Vec::new(),
825+
Vec::new(),
807826
);
808827
}
809828
archetypes
@@ -896,22 +915,24 @@ impl Archetypes {
896915
/// Specifically, it returns a tuple where the first element
897916
/// is the [`ArchetypeId`] that the given inputs belong to, and the second element is a boolean indicating whether a new archetype was created.
898917
///
899-
/// `table_components` and `sparse_set_components` must be sorted
918+
/// `table_components`, `sparse_set_components` and `resource_components` must be sorted
900919
///
901920
/// # Safety
902921
/// [`TableId`] must exist in tables
903-
/// `table_components` and `sparse_set_components` must exist in `components`
922+
/// `table_components`, `sparse_set_components` and `resource_components` must exist in `components`
904923
pub(crate) unsafe fn get_id_or_insert(
905924
&mut self,
906925
components: &Components,
907926
observers: &Observers,
908927
table_id: TableId,
909928
table_components: Vec<ComponentId>,
910929
sparse_set_components: Vec<ComponentId>,
930+
resource_components: Vec<ComponentId>,
911931
) -> (ArchetypeId, bool) {
912932
let archetype_identity = ArchetypeComponents {
913933
sparse_set_components: sparse_set_components.into_boxed_slice(),
914934
table_components: table_components.into_boxed_slice(),
935+
resource_components: resource_components.into_boxed_slice(),
915936
};
916937

917938
let archetypes = &mut self.archetypes;
@@ -922,6 +943,7 @@ impl Archetypes {
922943
let ArchetypeComponents {
923944
table_components,
924945
sparse_set_components,
946+
resource_components,
925947
} = vacant.key();
926948
let id = ArchetypeId::new(archetypes.len());
927949
archetypes.push(Archetype::new(
@@ -932,6 +954,7 @@ impl Archetypes {
932954
table_id,
933955
table_components.iter().copied(),
934956
sparse_set_components.iter().copied(),
957+
resource_components.iter().copied(),
935958
));
936959
vacant.insert(id);
937960
(id, true)

crates/bevy_ecs/src/bundle/info.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
},
1818
entity::Entity,
1919
query::DebugCheckedUnwrap as _,
20-
storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow},
20+
storage::{ResourceStorages, SparseSetIndex, SparseSets, Storages, Table, TableRow},
2121
};
2222

2323
/// For a specific [`World`], this stores a unique value identifying a type of a registered [`Bundle`].
@@ -240,6 +240,7 @@ impl BundleInfo {
240240
&self,
241241
table: &mut Table,
242242
sparse_sets: &mut SparseSets,
243+
resource_storages: &mut ResourceStorages,
243244
bundle_component_status: &S,
244245
required_components: impl Iterator<Item = &'a RequiredComponentConstructor>,
245246
entity: Entity,
@@ -294,6 +295,22 @@ impl BundleInfo {
294295
}
295296
}
296297
}
298+
StorageType::Resource => {
299+
let resource_storage =
300+
// SAFETY: If component_id is in self.component_ids, BundleInfo::new ensures that
301+
// a resource storage exists for the component.
302+
unsafe { resource_storages.get_mut(component_id).debug_checked_unwrap() };
303+
match (status, insert_mode) {
304+
(ComponentStatus::Added, _) | (_, InsertMode::Replace) => {
305+
resource_storage.insert(entity, component_ptr, change_tick, caller);
306+
}
307+
(ComponentStatus::Existing, InsertMode::Keep) => {
308+
if let Some(drop_fn) = resource_storage.get_drop() {
309+
drop_fn(component_ptr);
310+
}
311+
}
312+
}
313+
}
297314
}
298315
bundle_component += 1;
299316
});
@@ -302,6 +319,7 @@ impl BundleInfo {
302319
required_component.initialize(
303320
table,
304321
sparse_sets,
322+
resource_storages,
305323
change_tick,
306324
table_row,
307325
entity,
@@ -325,6 +343,7 @@ impl BundleInfo {
325343
pub(crate) unsafe fn initialize_required_component(
326344
table: &mut Table,
327345
sparse_sets: &mut SparseSets,
346+
resource_storages: &mut ResourceStorages,
328347
change_tick: Tick,
329348
table_row: TableRow,
330349
entity: Entity,
@@ -349,6 +368,13 @@ impl BundleInfo {
349368
unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
350369
sparse_set.insert(entity, component_ptr, change_tick, caller);
351370
}
371+
StorageType::Resource => {
372+
let resource_storage=
373+
// SAFETY: If component_id is in required_components, BundleInfo::new requires that
374+
// a sparse set exists for the component.
375+
unsafe { resource_storages.get_mut(component_id).debug_checked_unwrap() };
376+
resource_storage.insert(entity, component_ptr, change_tick, caller);
377+
}
352378
}
353379
}
354380
}

0 commit comments

Comments
 (0)