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

[Merged by Bors] - Reliable change detection #1471

Closed
wants to merge 43 commits into from
Closed
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
9a2c917
Counter-based reliable change detection
Davier Mar 7, 2021
f31a329
Change the system counters from Option<u32> to u32
Davier Mar 8, 2021
0dcf832
Check and fix old counters before they overflow
Davier Mar 8, 2021
c85cdda
Add Not<T> query transformer
Davier Mar 8, 2021
255d9a6
Remove Mutated<T>
Davier Mar 8, 2021
c2f265a
Simplify Changed<T> and Added<T> implementations
Davier Mar 8, 2021
f15d9ee
Inline some functions
Davier Mar 8, 2021
4a1dcf9
Fix duplicated resource counter initialization
Davier Mar 9, 2021
9318ab1
Improve doc comments
Davier Mar 10, 2021
10082e8
Atomic ordering
Davier Mar 10, 2021
dc19ca1
Warn when unrun systems mail fail to detect changes
Davier Mar 10, 2021
7700267
Cleaned up nits
alice-i-cecile Mar 10, 2021
5a7f0db
Updated outdated safety comment
alice-i-cecile Mar 10, 2021
19d3bf4
Fixed Option<Res> impl
alice-i-cecile Mar 11, 2021
cefe8b7
Merge branch 'main' into reliable-change-detection
alice-i-cecile Mar 11, 2021
dfb49d6
Fixed bad merge
alice-i-cecile Mar 11, 2021
3702731
cargo fmt
Davier Mar 11, 2021
38b3e25
Add unique() to DirectQuery
Davier Mar 11, 2021
7d38cc4
Remove DirectQuery
Davier Mar 13, 2021
c6d8e8d
Remove dbg!
Davier Mar 13, 2021
0406cac
Change '-1' to 'u32::MAX' in comments
Davier Mar 13, 2021
b40987d
Fix doc tests
Davier Mar 13, 2021
79ead84
Improve doc comment for `Not`
Davier Mar 13, 2021
34ec8ea
Remove Not
Davier Mar 14, 2021
def2980
Rename Counters to ChangeTrackers
Davier Mar 14, 2021
4bd7a28
Merge branch 'main' into reliable-change-detection
Davier Mar 14, 2021
d3836a2
global_system_counter -> change_tick
cart Mar 16, 2021
b8b1fe6
exclusive_system_counter -> last_change_tick
cart Mar 16, 2021
602ffc5
system_counter -> last_change_tick
cart Mar 16, 2021
e2423b2
world::clear_trackers() updates change_tick
cart Mar 16, 2021
5dcf252
more tick/tracker renames
cart Mar 17, 2021
182e60b
more counter to tick renames
cart Mar 17, 2021
954086c
test tick wrapover
Davier Mar 18, 2021
142293f
rename MAX_TIME_SINCE_LAST_CHECK -> MIN_TIME_SINCE_LAST_CHECK
Davier Mar 18, 2021
ae3f3aa
even more renames
Davier Mar 18, 2021
27a7292
comment change detection
Davier Mar 18, 2021
5c4927c
cargo fmt
Davier Mar 18, 2021
a8075a2
Change default tick values
Davier Mar 18, 2021
7713983
Re-add and adapt removed test
Davier Mar 18, 2021
3922267
Simplify clear_trackers
Davier Mar 18, 2021
59f8c85
Fix merge issue
Davier Mar 18, 2021
344ae7b
Test Changed queries
Davier Mar 19, 2021
b03e07e
cargo fmt
Davier Mar 19, 2021
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
4 changes: 4 additions & 0 deletions crates/bevy_core/src/time/fixed_timestep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,8 @@ impl System for FixedTimestep {
);
}
}

fn check_change_tick(&mut self, change_tick: u32) {
self.internal_system.check_change_tick(change_tick);
}
}
8 changes: 5 additions & 3 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,12 @@ pub fn impl_query_set(_input: TokenStream) -> TokenStream {
#[inline]
unsafe fn get_param(
state: &'a mut Self,
_system_state: &'a SystemState,
system_state: &'a SystemState,
world: &'a World,
change_tick: u32,
) -> Self::Item {
let (#(#query,)*) = &state.0;
QuerySet((#(Query::new(world, #query),)*))
QuerySet((#(Query::new(world, #query, system_state.last_change_tick, change_tick),)*))
}
}

Expand Down Expand Up @@ -402,9 +403,10 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
state: &'a mut Self,
system_state: &'a #path::system::SystemState,
world: &'a #path::world::World,
change_tick: u32,
) -> Self::Item {
#struct_name {
#(#fields: <<#field_types as SystemParam>::Fetch as #path::system::SystemParamFetch>::get_param(&mut state.state.#field_indices, system_state, world),)*
#(#fields: <<#field_types as SystemParam>::Fetch as #path::system::SystemParamFetch>::get_param(&mut state.state.#field_indices, system_state, world, change_tick),)*
#(#ignored_fields: <#ignored_field_types>::default(),)*
}
}
Expand Down
13 changes: 9 additions & 4 deletions crates/bevy_ecs/src/archetype.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
bundle::BundleId,
component::{ComponentFlags, ComponentId, StorageType},
component::{ComponentId, StorageType},
entity::{Entity, EntityLocation},
storage::{Column, SparseArray, SparseSet, SparseSetIndex, TableId},
};
Expand Down Expand Up @@ -36,9 +36,14 @@ impl ArchetypeId {
}
}

pub enum ComponentStatus {
Added,
Mutated,
}

alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
pub struct FromBundle {
pub archetype_id: ArchetypeId,
pub bundle_flags: Vec<ComponentFlags>,
pub bundle_status: Vec<ComponentStatus>,
}

#[derive(Default)]
Expand Down Expand Up @@ -70,13 +75,13 @@ impl Edges {
&mut self,
bundle_id: BundleId,
archetype_id: ArchetypeId,
bundle_flags: Vec<ComponentFlags>,
bundle_status: Vec<ComponentStatus>,
) {
self.from_bundle.insert(
bundle_id,
FromBundle {
archetype_id,
bundle_flags,
bundle_status,
},
);
}
Expand Down
35 changes: 30 additions & 5 deletions crates/bevy_ecs/src/bundle.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
pub use bevy_ecs_macros::Bundle;

use crate::{
component::{Component, ComponentFlags, ComponentId, Components, StorageType, TypeInfo},
archetype::ComponentStatus,
component::{Component, ComponentId, ComponentTicks, Components, StorageType, TypeInfo},
entity::Entity,
storage::{SparseSetIndex, SparseSets, Table},
};
Expand Down Expand Up @@ -123,32 +124,56 @@ pub struct BundleInfo {
impl BundleInfo {
/// # Safety
/// table row must exist, entity must be valid
#[allow(clippy::clippy::too_many_arguments)]
#[inline]
pub(crate) unsafe fn write_components<T: Bundle>(
&self,
sparse_sets: &mut SparseSets,
entity: Entity,
table: &Table,
table_row: usize,
bundle_flags: &[ComponentFlags],
bundle_status: &[ComponentStatus],
bundle: T,
change_tick: u32,
) {
// NOTE: get_components calls this closure on each component in "bundle order".
// bundle_info.component_ids are also in "bundle order"
let mut bundle_component = 0;
bundle.get_components(|component_ptr| {
// SAFE: component_id was initialized by get_dynamic_bundle_info
let component_id = *self.component_ids.get_unchecked(bundle_component);
let flags = *bundle_flags.get_unchecked(bundle_component);
let component_status = bundle_status.get_unchecked(bundle_component);
match self.storage_types[bundle_component] {
StorageType::Table => {
let column = table.get_column(component_id).unwrap();
column.set_unchecked(table_row, component_ptr);
column.get_flags_unchecked_mut(table_row).insert(flags);
let column_status = column.get_ticks_unchecked_mut(table_row);
match component_status {
ComponentStatus::Added => {
*column_status = ComponentTicks::new(change_tick);
}
ComponentStatus::Mutated => {
column_status.set_changed(change_tick);
}
}
}
StorageType::SparseSet => {
let sparse_set = sparse_sets.get_mut(component_id).unwrap();
sparse_set.insert(entity, component_ptr, flags);
match component_status {
ComponentStatus::Added => {
sparse_set.insert(
entity,
component_ptr,
ComponentTicks::new(change_tick),
);
}
ComponentStatus::Mutated => {
sparse_set
.get_ticks(entity)
.unwrap()
.set_changed(change_tick);
}
}
}
}
bundle_component += 1;
Expand Down
52 changes: 47 additions & 5 deletions crates/bevy_ecs/src/component/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ mod type_info;
pub use type_info::*;

use crate::storage::SparseSetIndex;
use bitflags::bitflags;
use std::{
alloc::Layout,
any::{Any, TypeId},
Expand Down Expand Up @@ -303,9 +302,52 @@ impl Components {
}
}

bitflags! {
pub struct ComponentFlags: u8 {
const ADDED = 1;
const MUTATED = 2;
#[derive(Copy, Clone, Debug)]
pub struct ComponentTicks {
pub(crate) added: u32,
pub(crate) changed: u32,
}

impl ComponentTicks {
#[inline]
pub fn is_added(&self, last_change_tick: u32, change_tick: u32) -> bool {
let component_age = change_tick.wrapping_sub(self.added);
let system_age = change_tick.wrapping_sub(last_change_tick);

component_age < system_age
}

#[inline]
pub fn is_changed(&self, last_change_tick: u32, change_tick: u32) -> bool {
let component_age = change_tick.wrapping_sub(self.changed);
let system_age = change_tick.wrapping_sub(last_change_tick);

component_age < system_age
}

pub(crate) fn new(change_tick: u32) -> Self {
Self {
added: change_tick,
changed: change_tick,
}
}

pub(crate) fn check_ticks(&mut self, change_tick: u32) {
check_tick(&mut self.added, change_tick);
check_tick(&mut self.changed, change_tick);
}

#[inline]
pub(crate) fn set_changed(&mut self, change_tick: u32) {
self.changed = change_tick;
}
}

fn check_tick(last_change_tick: &mut u32, change_tick: u32) {
let tick_delta = change_tick.wrapping_sub(*last_change_tick);
const MAX_DELTA: u32 = (u32::MAX / 4) * 3;
// Clamp to max delta
if tick_delta > MAX_DELTA {
*last_change_tick = change_tick.wrapping_sub(MAX_DELTA);
}
}
Loading