Skip to content

Commit

Permalink
Migrate to StaticSystemParam
Browse files Browse the repository at this point in the history
Remove `RunSystem`
  • Loading branch information
DJMcNab committed Feb 11, 2022
1 parent 11cd091 commit ae5f0bd
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 141 deletions.
79 changes: 1 addition & 78 deletions crates/bevy_ecs/src/system/function_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
query::{Access, FilteredAccessSet},
system::{
check_system_change_tick, ReadOnlySystemParamFetch, System, SystemParam, SystemParamFetch,
SystemParamItem, SystemParamState,
SystemParamState,
},
world::{World, WorldId},
};
Expand Down Expand Up @@ -46,11 +46,6 @@ impl SystemMeta {
pub fn set_non_send(&mut self) {
self.is_send = false;
}

#[inline]
pub(crate) fn check_change_tick(&mut self, change_tick: u32) {
check_system_change_tick(&mut self.last_change_tick, change_tick, self.name.as_ref());
}
}

// TODO: Actually use this in FunctionSystem. We should probably only do this once Systems are constructed using a World reference
Expand Down Expand Up @@ -126,10 +121,6 @@ impl<Param: SystemParam> SystemState<Param> {
self.world_id == world.id()
}

pub(crate) fn new_archetype(&mut self, archetype: &Archetype) {
self.param_state.new_archetype(archetype, &mut self.meta);
}

fn validate_world_and_update_archetypes(&mut self, world: &World) {
assert!(self.matches_world(world), "Encountered a mismatched World. A SystemState cannot be used with Worlds other than the one it was created with.");
let archetypes = world.archetypes();
Expand Down Expand Up @@ -168,74 +159,6 @@ impl<Param: SystemParam> SystemState<Param> {
}
}

/// A trait for defining systems with a [`SystemParam`] associated type.
///
/// This facilitates the creation of systems that are generic over some trait
/// and that use that trait's associated types as `SystemParam`s.
pub trait RunSystem: Send + Sync + 'static {
/// The `SystemParam` type passed to the system when it runs.
type Param: SystemParam;

/// Runs the system.
fn run(param: SystemParamItem<Self::Param>);

/// Creates a concrete instance of the system for the specified `World`.
fn system(world: &mut World) -> ParamSystem<Self::Param> {
ParamSystem {
run: Self::run,
state: SystemState::new(world),
}
}
}

pub struct ParamSystem<P: SystemParam> {
state: SystemState<P>,
run: fn(SystemParamItem<P>),
}

impl<P: SystemParam + 'static> System for ParamSystem<P> {
type In = ();

type Out = ();

fn name(&self) -> Cow<'static, str> {
self.state.meta().name.clone()
}

fn new_archetype(&mut self, archetype: &Archetype) {
self.state.new_archetype(archetype);
}

fn component_access(&self) -> &Access<ComponentId> {
self.state.meta().component_access_set.combined_access()
}

fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
&self.state.meta().archetype_component_access
}

fn is_send(&self) -> bool {
self.state.meta().is_send()
}

unsafe fn run_unsafe(&mut self, _input: Self::In, world: &World) -> Self::Out {
let param = self.state.get_unchecked_manual(world);
(self.run)(param);
}

fn apply_buffers(&mut self, world: &mut World) {
self.state.apply(world);
}

fn initialize(&mut self, _world: &mut World) {
// already initialized by nature of the SystemState being constructed
}

fn check_change_tick(&mut self, change_tick: u32) {
self.state.meta.check_change_tick(change_tick);
}
}

/// Conversion trait to turn something into a [`System`].
///
/// Use this to get a system from a function. Also note that every system implements this trait as
Expand Down
67 changes: 28 additions & 39 deletions crates/bevy_render/src/render_asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bevy_app::{App, Plugin};
use bevy_asset::{Asset, AssetEvent, Assets, Handle};
use bevy_ecs::{
prelude::*,
system::{lifetimeless::*, RunSystem, SystemParam, SystemParamItem},
system::{StaticSystemParam, SystemParam, SystemParamItem},
};
use bevy_utils::{HashMap, HashSet};
use std::marker::PhantomData;
Expand Down Expand Up @@ -55,13 +55,12 @@ impl<A: RenderAsset> Default for RenderAssetPlugin<A> {
impl<A: RenderAsset> Plugin for RenderAssetPlugin<A> {
fn build(&self, app: &mut App) {
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
let prepare_asset_system = PrepareAssetSystem::<A>::system(&mut render_app.world);
render_app
.init_resource::<ExtractedAssets<A>>()
.init_resource::<RenderAssets<A>>()
.init_resource::<PrepareNextFrameAssets<A>>()
.add_system_to_stage(RenderStage::Extract, extract_render_asset::<A>)
.add_system_to_stage(RenderStage::Prepare, prepare_asset_system);
.add_system_to_stage(RenderStage::Prepare, prepare_assets::<A>);
}
}
}
Expand Down Expand Up @@ -122,14 +121,6 @@ fn extract_render_asset<A: RenderAsset>(
})
}

/// Specifies all ECS data required by [`PrepareAssetSystem`].
pub type RenderAssetParams<R> = (
SResMut<ExtractedAssets<R>>,
SResMut<RenderAssets<R>>,
SResMut<PrepareNextFrameAssets<R>>,
<R as RenderAsset>::Param,
);

// TODO: consider storing inside system?
/// All assets that should be prepared next frame.
pub struct PrepareNextFrameAssets<A: RenderAsset> {
Expand All @@ -146,38 +137,36 @@ impl<A: RenderAsset> Default for PrepareNextFrameAssets<A> {

/// This system prepares all assets of the corresponding [`RenderAsset`] type
/// which where extracted this frame for the GPU.
pub struct PrepareAssetSystem<R: RenderAsset>(PhantomData<R>);

impl<R: RenderAsset> RunSystem for PrepareAssetSystem<R> {
type Param = RenderAssetParams<R>;

fn run(
(mut extracted_assets, mut render_assets, mut prepare_next_frame, mut param): SystemParamItem<Self::Param>,
) {
let mut queued_assets = std::mem::take(&mut prepare_next_frame.assets);
for (handle, extracted_asset) in queued_assets.drain(..) {
match R::prepare_asset(extracted_asset, &mut param) {
Ok(prepared_asset) => {
render_assets.insert(handle, prepared_asset);
}
Err(PrepareAssetError::RetryNextUpdate(extracted_asset)) => {
prepare_next_frame.assets.push((handle, extracted_asset));
}
fn prepare_assets<R: RenderAsset>(
mut extracted_assets: ResMut<ExtractedAssets<R>>,
mut render_assets: ResMut<RenderAssets<R>>,
mut prepare_next_frame: ResMut<PrepareNextFrameAssets<R>>,
param: StaticSystemParam<<R as RenderAsset>::Param>,
) {
let mut param = param.inner();
let mut queued_assets = std::mem::take(&mut prepare_next_frame.assets);
for (handle, extracted_asset) in queued_assets.drain(..) {
match R::prepare_asset(extracted_asset, &mut param) {
Ok(prepared_asset) => {
render_assets.insert(handle, prepared_asset);
}
Err(PrepareAssetError::RetryNextUpdate(extracted_asset)) => {
prepare_next_frame.assets.push((handle, extracted_asset));
}
}
}

for removed in std::mem::take(&mut extracted_assets.removed) {
render_assets.remove(&removed);
}
for removed in std::mem::take(&mut extracted_assets.removed) {
render_assets.remove(&removed);
}

for (handle, extracted_asset) in std::mem::take(&mut extracted_assets.extracted) {
match R::prepare_asset(extracted_asset, &mut param) {
Ok(prepared_asset) => {
render_assets.insert(handle, prepared_asset);
}
Err(PrepareAssetError::RetryNextUpdate(extracted_asset)) => {
prepare_next_frame.assets.push((handle, extracted_asset));
}
for (handle, extracted_asset) in std::mem::take(&mut extracted_assets.extracted) {
match R::prepare_asset(extracted_asset, &mut param) {
Ok(prepared_asset) => {
render_assets.insert(handle, prepared_asset);
}
Err(PrepareAssetError::RetryNextUpdate(extracted_asset)) => {
prepare_next_frame.assets.push((handle, extracted_asset));
}
}
}
Expand Down
36 changes: 12 additions & 24 deletions crates/bevy_render/src/render_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ use bevy_ecs::{
component::Component,
prelude::*,
query::{FilterFetch, QueryItem, WorldQuery},
system::{
lifetimeless::{Read, SCommands, SQuery},
RunSystem, SystemParamItem,
},
system::{lifetimeless::Read, StaticSystemParam},
};
use std::{marker::PhantomData, ops::Deref};

Expand Down Expand Up @@ -142,9 +139,8 @@ where
<C::Filter as WorldQuery>::Fetch: FilterFetch,
{
fn build(&self, app: &mut App) {
let system = ExtractComponentSystem::<C>::system(&mut app.world);
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
render_app.add_system_to_stage(RenderStage::Extract, system);
render_app.add_system_to_stage(RenderStage::Extract, extract_components::<C>);
}
}
}
Expand All @@ -160,25 +156,17 @@ impl<T: Asset> ExtractComponent for Handle<T> {
}

/// This system extracts all components of the corresponding [`ExtractComponent`] type.
pub struct ExtractComponentSystem<C: ExtractComponent>(PhantomData<C>);

impl<C: ExtractComponent> RunSystem for ExtractComponentSystem<C>
where
fn extract_components<C: ExtractComponent>(
mut commands: Commands,
mut previous_len: Local<usize>,
mut query: StaticSystemParam<Query<(Entity, C::Query), C::Filter>>,
) where
<C::Filter as WorldQuery>::Fetch: FilterFetch,
{
type Param = (
SCommands,
// the previous amount of extracted components
Local<'static, usize>,
SQuery<(Entity, C::Query), C::Filter>,
);

fn run((mut commands, mut previous_len, mut query): SystemParamItem<Self::Param>) {
let mut values = Vec::with_capacity(*previous_len);
for (entity, query_item) in query.iter_mut() {
values.push((entity, (C::extract_component(query_item),)));
}
*previous_len = values.len();
commands.insert_or_spawn_batch(values);
let mut values = Vec::with_capacity(*previous_len);
for (entity, query_item) in query.iter_mut() {
values.push((entity, (C::extract_component(query_item),)));
}
*previous_len = values.len();
commands.insert_or_spawn_batch(values);
}

0 comments on commit ae5f0bd

Please sign in to comment.