Skip to content

Commit d5a7330

Browse files
authored
System sets and parallel executor v2 (#1144)
System sets and parallel executor v2
1 parent b71ada0 commit d5a7330

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3169
-1358
lines changed

crates/bevy_app/src/app.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::app_builder::AppBuilder;
2-
use bevy_ecs::{Resources, Schedule, World};
2+
use bevy_ecs::{Resources, Schedule, Stage, World};
33
#[cfg(feature = "trace")]
44
use bevy_utils::tracing::info_span;
55

@@ -53,8 +53,7 @@ impl App {
5353
}
5454

5555
pub fn update(&mut self) {
56-
self.schedule
57-
.initialize_and_run(&mut self.world, &mut self.resources);
56+
self.schedule.run(&mut self.world, &mut self.resources);
5857
}
5958

6059
pub fn run(mut self) {

crates/bevy_app/src/app_builder.rs

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use crate::{
55
stage, startup_stage, PluginGroup, PluginGroupBuilder,
66
};
77
use bevy_ecs::{
8-
clear_trackers_system, FromResources, IntoSystem, Resource, Resources, RunOnce, Schedule,
9-
Stage, StateStage, System, SystemStage, World,
8+
clear_trackers_system, FromResources, IntoExclusiveSystem, IntoSystem, Resource, Resources,
9+
RunOnce, Schedule, Stage, StateStage, SystemDescriptor, SystemStage, World,
1010
};
1111
use bevy_utils::tracing::debug;
1212

@@ -24,7 +24,7 @@ impl Default for AppBuilder {
2424
app_builder
2525
.add_default_stages()
2626
.add_event::<AppExit>()
27-
.add_system_to_stage(stage::LAST, clear_trackers_system.system());
27+
.add_system_to_stage(stage::LAST, clear_trackers_system.exclusive_system());
2828
app_builder
2929
}
3030
}
@@ -125,60 +125,69 @@ impl AppBuilder {
125125
self
126126
}
127127

128-
pub fn add_system<S: System<In = (), Out = ()>>(&mut self, system: S) -> &mut Self {
128+
pub fn add_system(&mut self, system: impl Into<SystemDescriptor>) -> &mut Self {
129129
self.add_system_to_stage(stage::UPDATE, system)
130130
}
131131

132-
pub fn on_state_enter<T: Clone + Resource, S: System<In = (), Out = ()>>(
132+
pub fn add_system_to_stage(
133+
&mut self,
134+
stage_name: &'static str,
135+
system: impl Into<SystemDescriptor>,
136+
) -> &mut Self {
137+
self.app.schedule.add_system_to_stage(stage_name, system);
138+
self
139+
}
140+
141+
pub fn add_startup_system(&mut self, system: impl Into<SystemDescriptor>) -> &mut Self {
142+
self.add_startup_system_to_stage(startup_stage::STARTUP, system)
143+
}
144+
145+
pub fn add_startup_system_to_stage(
146+
&mut self,
147+
stage_name: &'static str,
148+
system: impl Into<SystemDescriptor>,
149+
) -> &mut Self {
150+
self.app
151+
.schedule
152+
.stage(stage::STARTUP, |schedule: &mut Schedule| {
153+
schedule.add_system_to_stage(stage_name, system)
154+
});
155+
self
156+
}
157+
158+
pub fn on_state_enter<T: Clone + Resource>(
133159
&mut self,
134160
stage: &str,
135161
state: T,
136-
system: S,
162+
system: impl Into<SystemDescriptor>,
137163
) -> &mut Self {
138164
self.stage(stage, |stage: &mut StateStage<T>| {
139165
stage.on_state_enter(state, system)
140166
})
141167
}
142168

143-
pub fn on_state_update<T: Clone + Resource, S: System<In = (), Out = ()>>(
169+
pub fn on_state_update<T: Clone + Resource>(
144170
&mut self,
145171
stage: &str,
146172
state: T,
147-
system: S,
173+
system: impl Into<SystemDescriptor>,
148174
) -> &mut Self {
149175
self.stage(stage, |stage: &mut StateStage<T>| {
150176
stage.on_state_update(state, system)
151177
})
152178
}
153179

154-
pub fn on_state_exit<T: Clone + Resource, S: System<In = (), Out = ()>>(
180+
pub fn on_state_exit<T: Clone + Resource>(
155181
&mut self,
156182
stage: &str,
157183
state: T,
158-
system: S,
184+
system: impl Into<SystemDescriptor>,
159185
) -> &mut Self {
160186
self.stage(stage, |stage: &mut StateStage<T>| {
161187
stage.on_state_exit(state, system)
162188
})
163189
}
164190

165-
pub fn add_startup_system_to_stage<S: System<In = (), Out = ()>>(
166-
&mut self,
167-
stage_name: &'static str,
168-
system: S,
169-
) -> &mut Self {
170-
self.app
171-
.schedule
172-
.stage(stage::STARTUP, |schedule: &mut Schedule| {
173-
schedule.add_system_to_stage(stage_name, system)
174-
});
175-
self
176-
}
177-
178-
pub fn add_startup_system<S: System<In = (), Out = ()>>(&mut self, system: S) -> &mut Self {
179-
self.add_startup_system_to_stage(startup_stage::STARTUP, system)
180-
}
181-
182191
pub fn add_default_stages(&mut self) -> &mut Self {
183192
self.add_stage(
184193
stage::STARTUP,
@@ -197,15 +206,6 @@ impl AppBuilder {
197206
.add_stage(stage::LAST, SystemStage::parallel())
198207
}
199208

200-
pub fn add_system_to_stage<S: System<In = (), Out = ()>>(
201-
&mut self,
202-
stage_name: &'static str,
203-
system: S,
204-
) -> &mut Self {
205-
self.app.schedule.add_system_to_stage(stage_name, system);
206-
self
207-
}
208-
209209
pub fn add_event<T>(&mut self) -> &mut Self
210210
where
211211
T: Send + Sync + 'static,
@@ -223,11 +223,11 @@ impl AppBuilder {
223223
self
224224
}
225225

226-
pub fn insert_thread_local_resource<T>(&mut self, resource: T) -> &mut Self
226+
pub fn insert_non_send_resource<T>(&mut self, resource: T) -> &mut Self
227227
where
228228
T: 'static,
229229
{
230-
self.app.resources.insert_thread_local(resource);
230+
self.app.resources.insert_non_send(resource);
231231
self
232232
}
233233

@@ -242,20 +242,18 @@ impl AppBuilder {
242242
let resource = R::from_resources(&self.resources());
243243
self.insert_resource(resource);
244244
}
245-
246245
self
247246
}
248247

249-
pub fn init_thread_local_resource<R>(&mut self) -> &mut Self
248+
pub fn init_non_send_resource<R>(&mut self) -> &mut Self
250249
where
251250
R: FromResources + 'static,
252251
{
253252
// See perf comment in init_resource
254-
if self.app.resources.get_thread_local::<R>().is_none() {
253+
if self.app.resources.get_non_send::<R>().is_none() {
255254
let resource = R::from_resources(&self.app.resources);
256-
self.app.resources.insert_thread_local(resource);
255+
self.app.resources.insert_non_send(resource);
257256
}
258-
259257
self
260258
}
261259

crates/bevy_audio/src/audio_output.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ where
6565
<P as Decodable>::Decoder: rodio::Source + Send + Sync,
6666
<<P as Decodable>::Decoder as Iterator>::Item: rodio::Sample + Send + Sync,
6767
{
68-
let audio_output = resources.get_thread_local::<AudioOutput<P>>().unwrap();
68+
let audio_output = resources.get_non_send::<AudioOutput<P>>().unwrap();
6969
let mut audio = resources.get_mut::<Audio<P>>().unwrap();
7070

7171
if let Some(audio_sources) = resources.get::<Assets<P>>() {

crates/bevy_audio/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ pub mod prelude {
1212

1313
use bevy_app::prelude::*;
1414
use bevy_asset::AddAsset;
15-
use bevy_ecs::IntoSystem;
15+
use bevy_ecs::IntoExclusiveSystem;
1616

1717
/// Adds support for audio playback to an App
1818
#[derive(Default)]
1919
pub struct AudioPlugin;
2020

2121
impl Plugin for AudioPlugin {
2222
fn build(&self, app: &mut AppBuilder) {
23-
app.init_thread_local_resource::<AudioOutput<AudioSource>>()
23+
app.init_non_send_resource::<AudioOutput<AudioSource>>()
2424
.add_asset::<AudioSource>()
2525
.init_asset_loader::<Mp3Loader>()
2626
.init_resource::<Audio<AudioSource>>()
2727
.add_system_to_stage(
2828
stage::POST_UPDATE,
29-
play_queued_audio_system::<AudioSource>.system(),
29+
play_queued_audio_system::<AudioSource>.exclusive_system(),
3030
);
3131
}
3232
}

crates/bevy_core/src/label.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,14 @@ pub(crate) fn entity_labels_system(
115115
#[cfg(test)]
116116
mod tests {
117117
use super::*;
118+
use bevy_ecs::Stage;
118119

119120
fn setup() -> (World, Resources, bevy_ecs::Schedule) {
120121
let world = World::new();
121122
let mut resources = Resources::default();
122123
resources.insert(EntityLabels::default());
123124
let mut schedule = bevy_ecs::Schedule::default();
124-
schedule.add_stage("test", SystemStage::serial());
125+
schedule.add_stage("test", SystemStage::single_threaded());
125126
schedule.add_system_to_stage("test", entity_labels_system.system());
126127
(world, resources, schedule)
127128
}
@@ -139,7 +140,7 @@ mod tests {
139140
let (mut world, mut resources, mut schedule) = setup();
140141

141142
let e1 = world.spawn((holy_cow(),));
142-
schedule.initialize_and_run(&mut world, &mut resources);
143+
schedule.run(&mut world, &mut resources);
143144

144145
let entity_labels = resources.get::<EntityLabels>().unwrap();
145146
assert_eq!(entity_labels.get("holy"), &[e1], "holy");
@@ -151,10 +152,10 @@ mod tests {
151152
fn add_labels() {
152153
let (mut world, mut resources, mut schedule) = setup();
153154
let e1 = world.spawn((holy_cow(),));
154-
schedule.initialize_and_run(&mut world, &mut resources);
155+
schedule.run(&mut world, &mut resources);
155156

156157
world.get_mut::<Labels>(e1).unwrap().insert("shalau");
157-
schedule.initialize_and_run(&mut world, &mut resources);
158+
schedule.run(&mut world, &mut resources);
158159

159160
let entity_labels = resources.get::<EntityLabels>().unwrap();
160161
assert_eq!(entity_labels.get("holy"), &[e1], "holy");
@@ -166,10 +167,10 @@ mod tests {
166167
fn remove_labels() {
167168
let (mut world, mut resources, mut schedule) = setup();
168169
let e1 = world.spawn((holy_cow(),));
169-
schedule.initialize_and_run(&mut world, &mut resources);
170+
schedule.run(&mut world, &mut resources);
170171

171172
world.get_mut::<Labels>(e1).unwrap().remove("holy");
172-
schedule.initialize_and_run(&mut world, &mut resources);
173+
schedule.run(&mut world, &mut resources);
173174

174175
let entity_labels = resources.get::<EntityLabels>().unwrap();
175176
assert_eq!(entity_labels.get("holy"), &[], "holy");
@@ -181,10 +182,10 @@ mod tests {
181182
fn removes_despawned_entity() {
182183
let (mut world, mut resources, mut schedule) = setup();
183184
let e1 = world.spawn((holy_cow(),));
184-
schedule.initialize_and_run(&mut world, &mut resources);
185+
schedule.run(&mut world, &mut resources);
185186

186187
world.despawn(e1).unwrap();
187-
schedule.initialize_and_run(&mut world, &mut resources);
188+
schedule.run(&mut world, &mut resources);
188189

189190
let entity_labels = resources.get::<EntityLabels>().unwrap();
190191
assert_eq!(entity_labels.get("holy"), &[], "holy");
@@ -196,10 +197,10 @@ mod tests {
196197
fn removes_labels_when_component_removed() {
197198
let (mut world, mut resources, mut schedule) = setup();
198199
let e1 = world.spawn((holy_cow(),));
199-
schedule.initialize_and_run(&mut world, &mut resources);
200+
schedule.run(&mut world, &mut resources);
200201

201202
world.remove_one::<Labels>(e1).unwrap();
202-
schedule.initialize_and_run(&mut world, &mut resources);
203+
schedule.run(&mut world, &mut resources);
203204

204205
let entity_labels = resources.get::<EntityLabels>().unwrap();
205206
assert_eq!(entity_labels.get("holy"), &[], "holy");
@@ -211,10 +212,10 @@ mod tests {
211212
fn adds_another_spawned_entity() {
212213
let (mut world, mut resources, mut schedule) = setup();
213214
let e1 = world.spawn((holy_cow(),));
214-
schedule.initialize_and_run(&mut world, &mut resources);
215+
schedule.run(&mut world, &mut resources);
215216

216217
let e2 = world.spawn((holy_shamoni(),));
217-
schedule.initialize_and_run(&mut world, &mut resources);
218+
schedule.run(&mut world, &mut resources);
218219

219220
let entity_labels = resources.get::<EntityLabels>().unwrap();
220221
assert_eq!(entity_labels.get("holy"), &[e1, e2], "holy");
@@ -227,13 +228,13 @@ mod tests {
227228
fn removes_despawned_entity_but_leaves_other() {
228229
let (mut world, mut resources, mut schedule) = setup();
229230
let e1 = world.spawn((holy_cow(),));
230-
schedule.initialize_and_run(&mut world, &mut resources);
231+
schedule.run(&mut world, &mut resources);
231232

232233
let e2 = world.spawn((holy_shamoni(),));
233-
schedule.initialize_and_run(&mut world, &mut resources);
234+
schedule.run(&mut world, &mut resources);
234235

235236
world.despawn(e1).unwrap();
236-
schedule.initialize_and_run(&mut world, &mut resources);
237+
schedule.run(&mut world, &mut resources);
237238

238239
let entity_labels = resources.get::<EntityLabels>().unwrap();
239240
assert_eq!(entity_labels.get("holy"), &[e2], "holy");

crates/bevy_core/src/time/fixed_timestep.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::Time;
2-
use bevy_ecs::{ArchetypeComponent, ShouldRun, System, SystemId, ThreadLocalExecution, TypeAccess};
2+
use bevy_ecs::{ArchetypeComponent, ShouldRun, System, SystemId, TypeAccess};
33
use bevy_utils::HashMap;
44
use std::{any::TypeId, borrow::Cow};
55

@@ -47,8 +47,9 @@ pub struct FixedTimestep {
4747
looping: bool,
4848
system_id: SystemId,
4949
label: Option<String>, // TODO: consider making this a TypedLabel
50-
resource_access: TypeAccess<TypeId>,
5150
archetype_access: TypeAccess<ArchetypeComponent>,
51+
component_access: TypeAccess<TypeId>,
52+
resource_access: TypeAccess<TypeId>,
5253
}
5354

5455
impl Default for FixedTimestep {
@@ -59,8 +60,9 @@ impl Default for FixedTimestep {
5960
accumulator: 0.0,
6061
looping: false,
6162
label: None,
62-
resource_access: Default::default(),
63+
component_access: Default::default(),
6364
archetype_access: Default::default(),
65+
resource_access: Default::default(),
6466
}
6567
}
6668
}
@@ -93,7 +95,7 @@ impl FixedTimestep {
9395
if self.accumulator >= self.step {
9496
self.accumulator -= self.step;
9597
self.looping = true;
96-
ShouldRun::YesAndLoop
98+
ShouldRun::YesAndCheckAgain
9799
} else {
98100
self.looping = false;
99101
ShouldRun::No
@@ -113,18 +115,22 @@ impl System for FixedTimestep {
113115
self.system_id
114116
}
115117

116-
fn update(&mut self, _world: &bevy_ecs::World) {}
118+
fn update_access(&mut self, _world: &bevy_ecs::World) {}
117119

118120
fn archetype_component_access(&self) -> &TypeAccess<ArchetypeComponent> {
119121
&self.archetype_access
120122
}
121123

124+
fn component_access(&self) -> &TypeAccess<TypeId> {
125+
&self.component_access
126+
}
127+
122128
fn resource_access(&self) -> &TypeAccess<TypeId> {
123129
&self.resource_access
124130
}
125131

126-
fn thread_local_execution(&self) -> ThreadLocalExecution {
127-
ThreadLocalExecution::Immediate
132+
fn is_non_send(&self) -> bool {
133+
false
128134
}
129135

130136
unsafe fn run_unsafe(
@@ -145,7 +151,7 @@ impl System for FixedTimestep {
145151
Some(result)
146152
}
147153

148-
fn run_thread_local(
154+
fn apply_buffers(
149155
&mut self,
150156
_world: &mut bevy_ecs::World,
151157
_resources: &mut bevy_ecs::Resources,

0 commit comments

Comments
 (0)