From 65bd41f3dcb90f675cf01f334749fe9e774095f3 Mon Sep 17 00:00:00 2001 From: james7132 Date: Mon, 9 May 2022 12:45:34 -0700 Subject: [PATCH 1/8] Remove task_pool parameter from par_for_each(_mut) --- .../bevy_ecs/ecs_bench_suite/heavy_compute.rs | 6 ++-- crates/bevy_ecs/src/lib.rs | 10 +++---- crates/bevy_ecs/src/query/state.rs | 28 +++++++++++-------- crates/bevy_ecs/src/system/query.rs | 22 +++++++++------ examples/ecs/parallel_query.rs | 16 ++++------- 5 files changed, 43 insertions(+), 39 deletions(-) diff --git a/benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs b/benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs index 4ddae1781ea1b..58dae22e89507 100644 --- a/benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs +++ b/benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs @@ -29,8 +29,8 @@ impl Benchmark { ) })); - fn sys(task_pool: Res, mut query: Query<(&mut Position, &mut Transform)>) { - query.par_for_each_mut(&task_pool, 128, |(mut pos, mut mat)| { + fn sys(mut query: Query<(&mut Position, &mut Transform)>) { + query.par_for_each_mut(128, |(mut pos, mut mat)| { for _ in 0..100 { mat.0 = mat.0.inverse(); } @@ -39,7 +39,7 @@ impl Benchmark { }); } - world.insert_resource(TaskPool::default()); + world.insert_resource(ComputeTaskPool(TaskPool::default())); let mut system = IntoSystem::into_system(sys); system.initialize(&mut world); system.update_archetype_component_access(&world); diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 15a5ac64a8d22..5c2f3a71316d6 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -56,7 +56,7 @@ mod tests { query::{Added, ChangeTrackers, Changed, FilteredAccess, With, Without, WorldQuery}, world::{Mut, World}, }; - use bevy_tasks::TaskPool; + use bevy_tasks::{ComputeTaskPool, TaskPool}; use std::{ any::TypeId, sync::{ @@ -373,7 +373,7 @@ mod tests { #[test] fn par_for_each_dense() { let mut world = World::new(); - let task_pool = TaskPool::default(); + world.insert_resource(ComputeTaskPool(TaskPool::default())); let e1 = world.spawn().insert(A(1)).id(); let e2 = world.spawn().insert(A(2)).id(); let e3 = world.spawn().insert(A(3)).id(); @@ -382,7 +382,7 @@ mod tests { let results = Arc::new(Mutex::new(Vec::new())); world .query::<(Entity, &A)>() - .par_for_each(&world, &task_pool, 2, |(e, &A(i))| { + .par_for_each(&world, 2, |(e, &A(i))| { results.lock().unwrap().push((e, i)); }); results.lock().unwrap().sort(); @@ -395,8 +395,7 @@ mod tests { #[test] fn par_for_each_sparse() { let mut world = World::new(); - - let task_pool = TaskPool::default(); + world.insert_resource(ComputeTaskPool(TaskPool::default())); let e1 = world.spawn().insert(SparseStored(1)).id(); let e2 = world.spawn().insert(SparseStored(2)).id(); let e3 = world.spawn().insert(SparseStored(3)).id(); @@ -405,7 +404,6 @@ mod tests { let results = Arc::new(Mutex::new(Vec::new())); world.query::<(Entity, &SparseStored)>().par_for_each( &world, - &task_pool, 2, |(e, &SparseStored(i))| results.lock().unwrap().push((e, i)), ); diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index e01d8df5f2b35..da81765bf1d24 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -10,7 +10,7 @@ use crate::{ storage::TableId, world::{World, WorldId}, }; -use bevy_tasks::TaskPool; +use bevy_tasks::ComputeTaskPool; use fixedbitset::FixedBitSet; use std::fmt; @@ -683,15 +683,17 @@ impl QueryState { ); } - /// Runs `func` on each query result in parallel using the given `task_pool`. + /// Runs `func` on each query result in parallel. /// /// This can only be called for read-only queries, see [`Self::par_for_each_mut`] for /// write-queries. + /// + /// # Panics + /// [`ComputeTaskPool`] is not stored as a resource in `world`. #[inline] pub fn par_for_each<'w, FN: Fn(ROQueryItem<'w, Q>) + Send + Sync + Clone>( &mut self, world: &'w World, - task_pool: &TaskPool, batch_size: usize, func: FN, ) { @@ -700,7 +702,6 @@ impl QueryState { self.update_archetypes(world); self.par_for_each_unchecked_manual::, FN>( world, - task_pool, batch_size, func, world.last_change_tick(), @@ -709,12 +710,14 @@ impl QueryState { } } - /// Runs `func` on each query result in parallel using the given `task_pool`. + /// Runs `func` on each query result in parallel. + /// + /// # Panics + /// [`ComputeTaskPool`] is not stored as a resource in `world`. #[inline] pub fn par_for_each_mut<'w, FN: Fn(QueryItem<'w, Q>) + Send + Sync + Clone>( &mut self, world: &'w mut World, - task_pool: &TaskPool, batch_size: usize, func: FN, ) { @@ -723,7 +726,6 @@ impl QueryState { self.update_archetypes(world); self.par_for_each_unchecked_manual::, FN>( world, - task_pool, batch_size, func, world.last_change_tick(), @@ -732,10 +734,13 @@ impl QueryState { } } - /// Runs `func` on each query result in parallel using the given `task_pool`. + /// Runs `func` on each query result in parallel. /// /// This can only be called for read-only queries. /// + /// # Panics + /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// /// # Safety /// /// This does not check for mutable query correctness. To be safe, make sure mutable queries @@ -744,14 +749,12 @@ impl QueryState { pub unsafe fn par_for_each_unchecked<'w, FN: Fn(QueryItem<'w, Q>) + Send + Sync + Clone>( &mut self, world: &'w World, - task_pool: &TaskPool, batch_size: usize, func: FN, ) { self.update_archetypes(world); self.par_for_each_unchecked_manual::, FN>( world, - task_pool, batch_size, func, world.last_change_tick(), @@ -827,6 +830,9 @@ impl QueryState { /// the current change tick are given. This is faster than the equivalent /// iter() method, but cannot be chained like a normal [`Iterator`]. /// + /// # Panics + /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// /// # Safety /// /// This does not check for mutable query correctness. To be safe, make sure mutable queries @@ -840,12 +846,12 @@ impl QueryState { >( &self, world: &'w World, - task_pool: &TaskPool, batch_size: usize, func: FN, last_change_tick: u32, change_tick: u32, ) { + let task_pool = world.resource::().clone(); // NOTE: If you are changing query iteration code, remember to update the following places, where relevant: // QueryIter, QueryIterationCursor, QueryState::for_each_unchecked_manual, QueryState::par_for_each_unchecked_manual task_pool.scope(|scope| { diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index c65c85b487433..b9e4d34bc98b3 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -7,7 +7,6 @@ use crate::{ }, world::{Mut, World}, }; -use bevy_tasks::TaskPool; use std::{any::TypeId, fmt::Debug}; /// Provides scoped access to components in a [`World`]. @@ -493,7 +492,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Runs `f` on each query result in parallel using the given [`TaskPool`]. + /// Runs `f` on each query result in parallel using the [`World`]'s [`ComputeTaskPool`]. /// /// This can only be called for immutable data, see [`Self::par_for_each_mut`] for /// mutable access. @@ -502,7 +501,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// /// The items in the query get sorted into batches. /// Internally, this function spawns a group of futures that each take on a `batch_size` sized section of the items (or less if the division is not perfect). - /// Then, the tasks in the [`TaskPool`] work through these futures. + /// Then, the tasks in the [`ComputeTaskPool`] work through these futures. /// /// You can use this value to tune between maximum multithreading ability (many small batches) and minimum parallelization overhead (few big batches). /// Rule of thumb: If the function body is (mostly) computationally expensive but there are not many items, a small batch size (=more batches) may help to even out the load. @@ -510,13 +509,16 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// /// # Arguments /// - ///* `task_pool` - The [`TaskPool`] to use ///* `batch_size` - The number of batches to spawn ///* `f` - The function to run on each item in the query + /// + /// # Panics + /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// + /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool #[inline] pub fn par_for_each<'this>( &'this self, - task_pool: &TaskPool, batch_size: usize, f: impl Fn(ROQueryItem<'this, Q>) + Send + Sync + Clone, ) { @@ -526,7 +528,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { self.state .par_for_each_unchecked_manual::, _>( self.world, - task_pool, batch_size, f, self.last_change_tick, @@ -535,12 +536,16 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { }; } - /// Runs `f` on each query result in parallel using the given [`TaskPool`]. + /// Runs `f` on each query result in parallel using the [`World`]'s [`ComputeTaskPool`]. /// See [`Self::par_for_each`] for more details. + /// + /// # Panics + /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// + /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool #[inline] pub fn par_for_each_mut<'a, FN: Fn(QueryItem<'a, Q>) + Send + Sync + Clone>( &'a mut self, - task_pool: &TaskPool, batch_size: usize, f: FN, ) { @@ -550,7 +555,6 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { self.state .par_for_each_unchecked_manual::, FN>( self.world, - task_pool, batch_size, f, self.last_change_tick, diff --git a/examples/ecs/parallel_query.rs b/examples/ecs/parallel_query.rs index a70eecf6d8b1a..a26706577d694 100644 --- a/examples/ecs/parallel_query.rs +++ b/examples/ecs/parallel_query.rs @@ -1,4 +1,4 @@ -use bevy::{prelude::*, tasks::prelude::*}; +use bevy::prelude::*; use rand::random; #[derive(Component, Deref)] @@ -21,26 +21,22 @@ fn spawn_system(mut commands: Commands, asset_server: Res) { } // Move sprites according to their velocity -fn move_system(pool: Res, mut sprites: Query<(&mut Transform, &Velocity)>) { +fn move_system(mut sprites: Query<(&mut Transform, &Velocity)>) { // Compute the new location of each sprite in parallel on the // ComputeTaskPool using batches of 32 sprites // - // This example is only for demonstrative purposes. Using a + // This example is only for demonstrative purposes. Using a // ParallelIterator for an inexpensive operation like addition on only 128 // elements will not typically be faster than just using a normal Iterator. // See the ParallelIterator documentation for more information on when // to use or not use ParallelIterator over a normal Iterator. - sprites.par_for_each_mut(&pool, 32, |(mut transform, velocity)| { + sprites.par_for_each_mut(32, |(mut transform, velocity)| { transform.translation += velocity.extend(0.0); }); } // Bounce sprites outside the window -fn bounce_system( - pool: Res, - windows: Res, - mut sprites: Query<(&Transform, &mut Velocity)>, -) { +fn bounce_system(windows: Res, mut sprites: Query<(&Transform, &mut Velocity)>) { let window = windows.primary(); let width = window.width(); let height = window.height(); @@ -51,7 +47,7 @@ fn bounce_system( sprites // Batch size of 32 is chosen to limit the overhead of // ParallelIterator, since negating a vector is very inexpensive. - .par_for_each_mut(&pool, 32, |(transform, mut v)| { + .par_for_each_mut(32, |(transform, mut v)| { if !(left < transform.translation.x && transform.translation.x < right && bottom < transform.translation.y From b1100392e43a04c86fd33f44b505e5a59586ca19 Mon Sep 17 00:00:00 2001 From: james7132 Date: Mon, 9 May 2022 12:53:45 -0700 Subject: [PATCH 2/8] Fix benchmarks --- benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs b/benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs index 58dae22e89507..71a8e6cc6a950 100644 --- a/benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs +++ b/benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs @@ -1,5 +1,5 @@ use bevy_ecs::prelude::*; -use bevy_tasks::TaskPool; +use bevy_tasks::{ComputeTaskPool, TaskPool}; use glam::*; #[derive(Component, Copy, Clone)] From cf10758fce4fbc03813223dadda319bbd42d8640 Mon Sep 17 00:00:00 2001 From: james7132 Date: Mon, 9 May 2022 13:10:47 -0700 Subject: [PATCH 3/8] Embed task pool into QueryState --- crates/bevy_ecs/src/query/state.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index da81765bf1d24..e605e96730a27 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -10,15 +10,16 @@ use crate::{ storage::TableId, world::{World, WorldId}, }; -use bevy_tasks::ComputeTaskPool; +use bevy_tasks::{ComputeTaskPool, TaskPool}; use fixedbitset::FixedBitSet; -use std::fmt; +use std::{fmt, ops::Deref}; use super::{QueryFetch, QueryItem, ROQueryFetch, ROQueryItem}; /// Provides scoped access to a [`World`] state according to a given [`WorldQuery`] and query filter. pub struct QueryState { world_id: WorldId, + task_pool: Option, pub(crate) archetype_generation: ArchetypeGeneration, pub(crate) matched_tables: FixedBitSet, pub(crate) matched_archetypes: FixedBitSet, @@ -59,6 +60,9 @@ impl QueryState { let mut state = Self { world_id: world.id(), + task_pool: world + .get_resource::() + .map(|task_pool| task_pool.deref().clone()), archetype_generation: ArchetypeGeneration::initial(), matched_table_ids: Vec::new(), matched_archetype_ids: Vec::new(), @@ -851,7 +855,10 @@ impl QueryState { last_change_tick: u32, change_tick: u32, ) { - let task_pool = world.resource::().clone(); + let task_pool = self + .task_pool + .clone() + .expect("Cannot iterate query in parallel. No ComputeTaskPool initialized."); // NOTE: If you are changing query iteration code, remember to update the following places, where relevant: // QueryIter, QueryIterationCursor, QueryState::for_each_unchecked_manual, QueryState::par_for_each_unchecked_manual task_pool.scope(|scope| { From 076db46fea5a55e247bab43cc362b9b4dcc0cda1 Mon Sep 17 00:00:00 2001 From: james7132 Date: Mon, 9 May 2022 13:45:45 -0700 Subject: [PATCH 4/8] Remove the clone --- crates/bevy_ecs/src/query/state.rs | 139 +++++++++++++++-------------- 1 file changed, 73 insertions(+), 66 deletions(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index e605e96730a27..d1463aeb7a672 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -855,79 +855,86 @@ impl QueryState { last_change_tick: u32, change_tick: u32, ) { - let task_pool = self - .task_pool - .clone() - .expect("Cannot iterate query in parallel. No ComputeTaskPool initialized."); // NOTE: If you are changing query iteration code, remember to update the following places, where relevant: // QueryIter, QueryIterationCursor, QueryState::for_each_unchecked_manual, QueryState::par_for_each_unchecked_manual - task_pool.scope(|scope| { - if QF::IS_DENSE && >::IS_DENSE { - let tables = &world.storages().tables; - for table_id in &self.matched_table_ids { - let table = &tables[*table_id]; - let mut offset = 0; - while offset < table.len() { - let func = func.clone(); - scope.spawn(async move { - let mut fetch = - QF::init(world, &self.fetch_state, last_change_tick, change_tick); - let mut filter = as Fetch>::init( - world, - &self.filter_state, - last_change_tick, - change_tick, - ); - let tables = &world.storages().tables; - let table = &tables[*table_id]; - fetch.set_table(&self.fetch_state, table); - filter.set_table(&self.filter_state, table); - let len = batch_size.min(table.len() - offset); - for table_index in offset..offset + len { - if !filter.table_filter_fetch(table_index) { - continue; + self.task_pool + .as_ref() + .expect("Cannot iterate query in parallel. No ComputeTaskPool initialized.") + .scope(|scope| { + if QF::IS_DENSE && >::IS_DENSE { + let tables = &world.storages().tables; + for table_id in &self.matched_table_ids { + let table = &tables[*table_id]; + let mut offset = 0; + while offset < table.len() { + let func = func.clone(); + scope.spawn(async move { + let mut fetch = QF::init( + world, + &self.fetch_state, + last_change_tick, + change_tick, + ); + let mut filter = as Fetch>::init( + world, + &self.filter_state, + last_change_tick, + change_tick, + ); + let tables = &world.storages().tables; + let table = &tables[*table_id]; + fetch.set_table(&self.fetch_state, table); + filter.set_table(&self.filter_state, table); + let len = batch_size.min(table.len() - offset); + for table_index in offset..offset + len { + if !filter.table_filter_fetch(table_index) { + continue; + } + let item = fetch.table_fetch(table_index); + func(item); } - let item = fetch.table_fetch(table_index); - func(item); - } - }); - offset += batch_size; + }); + offset += batch_size; + } } - } - } else { - let archetypes = &world.archetypes; - for archetype_id in &self.matched_archetype_ids { - let mut offset = 0; - let archetype = &archetypes[*archetype_id]; - while offset < archetype.len() { - let func = func.clone(); - scope.spawn(async move { - let mut fetch = - QF::init(world, &self.fetch_state, last_change_tick, change_tick); - let mut filter = as Fetch>::init( - world, - &self.filter_state, - last_change_tick, - change_tick, - ); - let tables = &world.storages().tables; - let archetype = &world.archetypes[*archetype_id]; - fetch.set_archetype(&self.fetch_state, archetype, tables); - filter.set_archetype(&self.filter_state, archetype, tables); - - let len = batch_size.min(archetype.len() - offset); - for archetype_index in offset..offset + len { - if !filter.archetype_filter_fetch(archetype_index) { - continue; + } else { + let archetypes = &world.archetypes; + for archetype_id in &self.matched_archetype_ids { + let mut offset = 0; + let archetype = &archetypes[*archetype_id]; + while offset < archetype.len() { + let func = func.clone(); + scope.spawn(async move { + let mut fetch = QF::init( + world, + &self.fetch_state, + last_change_tick, + change_tick, + ); + let mut filter = as Fetch>::init( + world, + &self.filter_state, + last_change_tick, + change_tick, + ); + let tables = &world.storages().tables; + let archetype = &world.archetypes[*archetype_id]; + fetch.set_archetype(&self.fetch_state, archetype, tables); + filter.set_archetype(&self.filter_state, archetype, tables); + + let len = batch_size.min(archetype.len() - offset); + for archetype_index in offset..offset + len { + if !filter.archetype_filter_fetch(archetype_index) { + continue; + } + func(fetch.archetype_fetch(archetype_index)); } - func(fetch.archetype_fetch(archetype_index)); - } - }); - offset += batch_size; + }); + offset += batch_size; + } } } - } - }); + }); } } From 12eefa183d22869600096d8ad0bd20aef6e2835a Mon Sep 17 00:00:00 2001 From: james7132 Date: Mon, 9 May 2022 15:43:10 -0700 Subject: [PATCH 5/8] Update docs --- crates/bevy_ecs/src/query/state.rs | 12 ++++++++---- crates/bevy_ecs/src/system/query.rs | 6 ++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index d1463aeb7a672..077706752b417 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -693,7 +693,8 @@ impl QueryState { /// write-queries. /// /// # Panics - /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// [`ComputeTaskPool`] was not stored in the world at initialzation. If using this from a query + /// that is being initialized and run from the ECS scheduler, this should never panic. #[inline] pub fn par_for_each<'w, FN: Fn(ROQueryItem<'w, Q>) + Send + Sync + Clone>( &mut self, @@ -717,7 +718,8 @@ impl QueryState { /// Runs `func` on each query result in parallel. /// /// # Panics - /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// [`ComputeTaskPool`] was not stored in the world at initialzation. If using this from a query + /// that is being initialized and run from the ECS scheduler, this should never panic. #[inline] pub fn par_for_each_mut<'w, FN: Fn(QueryItem<'w, Q>) + Send + Sync + Clone>( &mut self, @@ -743,7 +745,8 @@ impl QueryState { /// This can only be called for read-only queries. /// /// # Panics - /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// [`ComputeTaskPool`] was not stored in the world at initialzation. If using this from a query + /// that is being initialized and run from the ECS scheduler, this should never panic. /// /// # Safety /// @@ -835,7 +838,8 @@ impl QueryState { /// iter() method, but cannot be chained like a normal [`Iterator`]. /// /// # Panics - /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// [`ComputeTaskPool`] was not stored in the world at initialzation. If using this from a query + /// that is being initialized and run from the ECS scheduler, this should never panic. /// /// # Safety /// diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index b9e4d34bc98b3..350f2c50059dc 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -513,7 +513,8 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { ///* `f` - The function to run on each item in the query /// /// # Panics - /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// [`ComputeTaskPool`] was not stored in the world at initialzation. If using this from a query + /// that is being initialized and run from the ECS scheduler, this should never panic. /// /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool #[inline] @@ -540,7 +541,8 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// See [`Self::par_for_each`] for more details. /// /// # Panics - /// [`ComputeTaskPool`] is not stored as a resource in `world`. + /// [`ComputeTaskPool`] was not stored in the world at initialzation. If using this from a query + /// that is being initialized and run from the ECS scheduler, this should never panic. /// /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool #[inline] From 332e8518fff944e9ac2a3269556ce43d0959079a Mon Sep 17 00:00:00 2001 From: James Liu Date: Mon, 16 May 2022 10:42:07 -0700 Subject: [PATCH 6/8] Update docs. Co-authored-by: Alice Cecile --- crates/bevy_ecs/src/query/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 9957f3cf40c38..067c9b8507047 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -695,7 +695,7 @@ impl QueryState { /// write-queries. /// /// # Panics - /// [`ComputeTaskPool`] was not stored in the world at initialzation. If using this from a query + /// The [`ComputeTaskPool`] resource must be added to the `World` before using this method. If using this from a query /// that is being initialized and run from the ECS scheduler, this should never panic. #[inline] pub fn par_for_each<'w, FN: Fn(ROQueryItem<'w, Q>) + Send + Sync + Clone>( From 186fd5014d55405932315894572f459c0975520e Mon Sep 17 00:00:00 2001 From: James Liu Date: Mon, 16 May 2022 10:42:13 -0700 Subject: [PATCH 7/8] Update docs. Co-authored-by: Alice Cecile --- crates/bevy_ecs/src/query/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 067c9b8507047..0d3016edc737d 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -720,7 +720,7 @@ impl QueryState { /// Runs `func` on each query result in parallel. /// /// # Panics - /// [`ComputeTaskPool`] was not stored in the world at initialzation. If using this from a query + /// The [`ComputeTaskPool`] resource must be added to the `World` before using this method. If using this from a query /// that is being initialized and run from the ECS scheduler, this should never panic. #[inline] pub fn par_for_each_mut<'w, FN: Fn(QueryItem<'w, Q>) + Send + Sync + Clone>( From 88044d19bd3f5ec9518ee3f2024d7e3f0c1a536e Mon Sep 17 00:00:00 2001 From: James Liu Date: Mon, 16 May 2022 10:42:21 -0700 Subject: [PATCH 8/8] Update docs. Co-authored-by: Alice Cecile --- crates/bevy_ecs/src/system/query.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 350f2c50059dc..9e4b83519a5e3 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -513,7 +513,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { ///* `f` - The function to run on each item in the query /// /// # Panics - /// [`ComputeTaskPool`] was not stored in the world at initialzation. If using this from a query + /// The [`ComputeTaskPool`] resource must be added to the `World` before using this method. If using this from a query /// that is being initialized and run from the ECS scheduler, this should never panic. /// /// [`ComputeTaskPool`]: bevy_tasks::prelude::ComputeTaskPool