Skip to content
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

Track source location in change detection #14034

Merged
merged 26 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1c1af8f
Track callers for change detection
aevyrie Jun 26, 2024
aebbc27
use Location instead of String
aevyrie Jun 26, 2024
a5cbbd4
feat: create `change_detection_source` feature
BD103 Jul 27, 2024
7219b9c
refactor: use imports instead of full qualified path
BD103 Jul 27, 2024
60497cb
feat: store `Location` behind a `&'static`
BD103 Jul 27, 2024
c0b21e1
feat: feature flag change detection tracking
BD103 Jul 27, 2024
34e5601
fix: replaced components not being dropped
BD103 Jul 27, 2024
0dba2c7
chore: add `track_change_detection` feature to `bevy_internal` and `b…
BD103 Jul 27, 2024
2751878
fix: change detection example
BD103 Jul 27, 2024
3965c7c
Merge pull request #2 from BD103/changed-by
aevyrie Jul 27, 2024
f244435
Add change detection feature to documentation
aevyrie Jul 27, 2024
6093da0
Formatting
aevyrie Jul 27, 2024
e0a4ce1
Fix locations not updating in component mutation.
aevyrie Jul 27, 2024
9ef68fd
rename `caller` to `changed_by`
aevyrie Jul 28, 2024
ff2cf5f
Update change detection example to teach new features.
aevyrie Jul 28, 2024
6fff6e6
Merge branch 'main' into changed-by
aevyrie Jul 28, 2024
a5ef39b
Fix spelling
aevyrie Jul 28, 2024
c2bcdfd
Fix upstream compile error
aevyrie Jul 28, 2024
64cc652
Remove unused.
aevyrie Jul 28, 2024
83a96f6
Fix API gaps
aevyrie Jul 28, 2024
a397fb3
Expand example to include resources, and rename.
aevyrie Jul 28, 2024
7214af8
Revert image fix
aevyrie Jul 28, 2024
861425a
Update example readme
aevyrie Jul 28, 2024
88666cd
Update examples/ecs/change_detection.rs
aevyrie Jul 28, 2024
eafb34b
Merge branch 'main' into changed-by
aevyrie Jul 28, 2024
898f973
Update examples/ecs/change_detection.rs
aevyrie Jul 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ ios_simulator = ["bevy_internal/ios_simulator"]
# Enable built in global state machines
bevy_state = ["bevy_internal/bevy_state"]

# Enables source location tracking for change detection, which can assist with debugging
track_change_detection = ["bevy_internal/track_change_detection"]

# Enable function reflection
reflect_functions = ["bevy_internal/reflect_functions"]

Expand Down Expand Up @@ -1610,13 +1613,14 @@ category = "ECS (Entity Component System)"
wasm = false

[[example]]
name = "component_change_detection"
path = "examples/ecs/component_change_detection.rs"
name = "change_detection"
path = "examples/ecs/change_detection.rs"
doc-scrape-examples = true
required-features = ["track_change_detection"]

[package.metadata.example.component_change_detection]
name = "Component Change Detection"
description = "Change detection on components"
[package.metadata.example.change_detection]
name = "Change Detection"
description = "Change detection on components and resources"
category = "ECS (Entity Component System)"
wasm = false

Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_ecs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ categories = ["game-engines", "data-structures"]
rust-version = "1.77.0"

[features]
default = ["bevy_reflect"]
trace = []
multi_threaded = ["bevy_tasks/multi_threaded", "arrayvec"]
bevy_debug_stepping = []
default = ["bevy_reflect"]
serialize = ["dep:serde"]
track_change_detection = []

[dependencies]
bevy_ptr = { path = "../bevy_ptr", version = "0.15.0-dev" }
Expand Down
50 changes: 45 additions & 5 deletions crates/bevy_ecs/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use crate::{

use bevy_ptr::{ConstNonNull, OwningPtr};
use bevy_utils::{all_tuples, HashMap, HashSet, TypeIdMap};
#[cfg(feature = "track_change_detection")]
use std::panic::Location;
use std::ptr::NonNull;

/// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity.
Expand Down Expand Up @@ -401,6 +403,7 @@ impl BundleInfo {
table_row: TableRow,
change_tick: Tick,
bundle: T,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>,
) {
// NOTE: get_components calls this closure on each component in "bundle order".
// bundle_info.component_ids are also in "bundle order"
Expand All @@ -417,10 +420,22 @@ impl BundleInfo {
let status = unsafe { bundle_component_status.get_status(bundle_component) };
match status {
ComponentStatus::Added => {
column.initialize(table_row, component_ptr, change_tick);
column.initialize(
table_row,
component_ptr,
change_tick,
#[cfg(feature = "track_change_detection")]
caller,
);
}
ComponentStatus::Mutated => {
column.replace(table_row, component_ptr, change_tick);
column.replace(
table_row,
component_ptr,
change_tick,
#[cfg(feature = "track_change_detection")]
caller,
);
}
}
}
Expand All @@ -429,7 +444,13 @@ impl BundleInfo {
// SAFETY: If component_id is in self.component_ids, BundleInfo::new requires that
// a sparse set exists for the component.
unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
sparse_set.insert(entity, component_ptr, change_tick);
sparse_set.insert(
entity,
component_ptr,
change_tick,
#[cfg(feature = "track_change_detection")]
caller,
);
}
}
bundle_component += 1;
Expand Down Expand Up @@ -664,6 +685,7 @@ impl<'w> BundleInserter<'w> {
entity: Entity,
location: EntityLocation,
bundle: T,
#[cfg(feature = "track_change_detection")] caller: &'static core::panic::Location<'static>,
) -> EntityLocation {
let bundle_info = self.bundle_info.as_ref();
let add_bundle = self.add_bundle.as_ref();
Expand Down Expand Up @@ -706,6 +728,8 @@ impl<'w> BundleInserter<'w> {
location.table_row,
self.change_tick,
bundle,
#[cfg(feature = "track_change_detection")]
caller,
);

(archetype, location)
Expand Down Expand Up @@ -744,6 +768,8 @@ impl<'w> BundleInserter<'w> {
result.table_row,
self.change_tick,
bundle,
#[cfg(feature = "track_change_detection")]
caller,
);

(new_archetype, new_location)
Expand Down Expand Up @@ -823,6 +849,8 @@ impl<'w> BundleInserter<'w> {
move_result.new_row,
self.change_tick,
bundle,
#[cfg(feature = "track_change_detection")]
caller,
);

(new_archetype, new_location)
Expand Down Expand Up @@ -919,6 +947,7 @@ impl<'w> BundleSpawner<'w> {
&mut self,
entity: Entity,
bundle: T,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>,
) -> EntityLocation {
// SAFETY: We do not make any structural changes to the archetype graph through self.world so these pointers always remain valid
let bundle_info = self.bundle_info.as_ref();
Expand All @@ -941,6 +970,8 @@ impl<'w> BundleSpawner<'w> {
table_row,
self.change_tick,
bundle,
#[cfg(feature = "track_change_detection")]
caller,
);
entities.set(entity.index(), location);
location
Expand Down Expand Up @@ -969,11 +1000,20 @@ impl<'w> BundleSpawner<'w> {
/// # Safety
/// `T` must match this [`BundleInfo`]'s type
#[inline]
pub unsafe fn spawn<T: Bundle>(&mut self, bundle: T) -> Entity {
pub unsafe fn spawn<T: Bundle>(
&mut self,
bundle: T,
#[cfg(feature = "track_change_detection")] caller: &'static Location<'static>,
) -> Entity {
let entity = self.entities().alloc();
// SAFETY: entity is allocated (but non-existent), `T` matches this BundleInfo's type
unsafe {
self.spawn_non_existent(entity, bundle);
self.spawn_non_existent(
entity,
bundle,
#[cfg(feature = "track_change_detection")]
caller,
);
}
entity
}
Expand Down
Loading