-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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] - Make RenderStage::Extract
run on the render world
#4402
Conversation
Setup infrastructure for render app owns extract Commit 'progress' Finish API Cleverly avoid needing the param to be 'static This same trick can't work for `StaticSystemParam` fwiw This is because `StaticSystemParam`'s item needs to exactly reference the original param, whereas this just stores it Migrate to the new pattern Remove `spawn_and_forget` It's unused, and was only ever needed for the weird extract logic Fix clippy errors Remove the trick because it's actually stupid Add some docs Fixup docs
Setup infrastructure for render app owns extract Commit 'progress' Finish API Cleverly avoid needing the param to be 'static This same trick can't work for `StaticSystemParam` fwiw This is because `StaticSystemParam`'s item needs to exactly reference the original param, whereas this just stores it Migrate to the new pattern Remove `spawn_and_forget` It's unused, and was only ever needed for the weird extract logic Fix clippy errors Remove the trick because it's actually stupid Add some docs Fixup docs
Setup infrastructure for render app owns extract Commit 'progress' Finish API Cleverly avoid needing the param to be 'static This same trick can't work for `StaticSystemParam` fwiw This is because `StaticSystemParam`'s item needs to exactly reference the original param, whereas this just stores it Migrate to the new pattern Remove `spawn_and_forget` It's unused, and was only ever needed for the weird extract logic Fix clippy errors Remove the trick because it's actually stupid Add some docs Fixup docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks good, just one thing regarding ergonomics.
#[derive(Default)] | ||
pub struct RenderWorld(World); | ||
pub struct MainWorld(World); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably could use the Deref
derive macro we have.
Did you do any benchmarks to compare? |
As far as I remember, I was told to do this in discord, based on a visualisation? someone had created so I did it. I haven't benchmarked this. |
9ddd64d
to
5e350b7
Compare
Required for #4402. # Objective - derived `SystemParam` implementations were never `ReadOnlySystemParamFetch` - We want them to be, e.g. for `EventReader` ## Solution - If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
Required for #4402. # Objective - derived `SystemParam` implementations were never `ReadOnlySystemParamFetch` - We want them to be, e.g. for `EventReader` ## Solution - If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
Required for #4402. # Objective - derived `SystemParam` implementations were never `ReadOnlySystemParamFetch` - We want them to be, e.g. for `EventReader` ## Solution - If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
Required for #4402. # Objective - derived `SystemParam` implementations were never `ReadOnlySystemParamFetch` - We want them to be, e.g. for `EventReader` ## Solution - If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
Required for bevyengine#4402. # Objective - derived `SystemParam` implementations were never `ReadOnlySystemParamFetch` - We want them to be, e.g. for `EventReader` ## Solution - If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
Required for bevyengine#4402. # Objective - derived `SystemParam` implementations were never `ReadOnlySystemParamFetch` - We want them to be, e.g. for `EventReader` ## Solution - If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
@DJMcNab can you rebase this PR? I'd like to test the perf of it, but the merge conflicts are non-trivial. |
I'm not very keen to - I don't know that it's likely to land too, and rebasing is annoying because there's no easy way to find all of the extract systems. At least for the latter, we can warn if an extract system doesn't read |
Cleverly avoid needing the param to be 'static This same trick can't work for `StaticSystemParam` fwiw This is because `StaticSystemParam`'s item needs to exactly reference the original param, whereas this just stores it
It's unused, and was only ever needed for the weird extract logic Remove the trick because it's actually stupid
533125a
to
90659d4
Compare
bors r+ |
# Objective - Currently, the `Extract` `RenderStage` is executed on the main world, with the render world available as a resource. - However, when needing access to resources in the render world (e.g. to mutate them), the only way to do so was to get exclusive access to the whole `RenderWorld` resource. - This meant that effectively only one extract which wrote to resources could run at a time. - We didn't previously make `Extract`ing writing to the world a non-happy path, even though we want to discourage that. ## Solution - Move the extract stage to run on the render world. - Add the main world as a `MainWorld` resource. - Add an `Extract` `SystemParam` as a convenience to access a (read only) `SystemParam` in the main world during `Extract`. ## Future work It should be possible to avoid needing to use `get_or_spawn` for the render commands, since now the `Commands`' `Entities` matches up with the world being executed on. We need to determine how this interacts with #3519 It's theoretically possible to remove the need for the `value` method on `Extract`. However, that requires slightly changing the `SystemParam` interface, which would make it more complicated. That would probably mess up the `SystemState` api too. ## Todo I still need to add doc comments to `Extract`. --- ## Changelog ### Changed - The `Extract` `RenderStage` now runs on the render world (instead of the main world as before). You must use the `Extract` `SystemParam` to access the main world during the extract phase. Resources on the render world can now be accessed using `ResMut` during extract. ### Removed - `Commands::spawn_and_forget`. Use `Commands::get_or_spawn(e).insert_bundle(bundle)` instead ## Migration Guide The `Extract` `RenderStage` now runs on the render world (instead of the main world as before). You must use the `Extract` `SystemParam` to access the main world during the extract phase. `Extract` takes a single type parameter, which is any system parameter (such as `Res`, `Query` etc.). It will extract this from the main world, and returns the result of this extraction when `value` is called on it. For example, if previously your extract system looked like: ```rust fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) { for cloud in clouds.iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` the new version would be: ```rust fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) { for cloud in clouds.value().iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` The diff is: ```diff --- a/src/clouds.rs +++ b/src/clouds.rs @@ -1,5 +1,5 @@ -fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) { - for cloud in clouds.iter() { +fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) { + for cloud in clouds.value().iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` You can now also access resources from the render world using the normal system parameters during `Extract`: ```rust fn extract_assets(mut render_assets: ResMut<MyAssets>, source_assets: Extract<Res<MyAssets>>) { *render_assets = source_assets.clone(); } ``` Please note that all existing extract systems need to be updated to match this new style; even if they currently compile they will not run as expected. A warning will be emitted on a best-effort basis if this is not met. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
RenderStage::Extract
run on the render worldRenderStage::Extract
run on the render world
Following bevyengine#4402, it is now impossible to mutate the main world from the render world, so we split the update to the projection into a different system ran in the main world.
# Objective - Extracting resources currently always uses commands, which requires *at least* one additional move of the extracted value, as well as dynamic dispatch. - Addresses #4402 (comment) ## Solution - Write the resource into a `ResMut<R>` directly. - Fall-back to commands if the resource hasn't been added yet.
Following bevyengine#4402, it is now impossible to mutate the main world from the render world, so we split the update to the projection into a different system ran in the main world.
# Objective - Currently, the `Extract` `RenderStage` is executed on the main world, with the render world available as a resource. - However, when needing access to resources in the render world (e.g. to mutate them), the only way to do so was to get exclusive access to the whole `RenderWorld` resource. - This meant that effectively only one extract which wrote to resources could run at a time. - We didn't previously make `Extract`ing writing to the world a non-happy path, even though we want to discourage that. ## Solution - Move the extract stage to run on the render world. - Add the main world as a `MainWorld` resource. - Add an `Extract` `SystemParam` as a convenience to access a (read only) `SystemParam` in the main world during `Extract`. ## Future work It should be possible to avoid needing to use `get_or_spawn` for the render commands, since now the `Commands`' `Entities` matches up with the world being executed on. We need to determine how this interacts with bevyengine#3519 It's theoretically possible to remove the need for the `value` method on `Extract`. However, that requires slightly changing the `SystemParam` interface, which would make it more complicated. That would probably mess up the `SystemState` api too. ## Todo I still need to add doc comments to `Extract`. --- ## Changelog ### Changed - The `Extract` `RenderStage` now runs on the render world (instead of the main world as before). You must use the `Extract` `SystemParam` to access the main world during the extract phase. Resources on the render world can now be accessed using `ResMut` during extract. ### Removed - `Commands::spawn_and_forget`. Use `Commands::get_or_spawn(e).insert_bundle(bundle)` instead ## Migration Guide The `Extract` `RenderStage` now runs on the render world (instead of the main world as before). You must use the `Extract` `SystemParam` to access the main world during the extract phase. `Extract` takes a single type parameter, which is any system parameter (such as `Res`, `Query` etc.). It will extract this from the main world, and returns the result of this extraction when `value` is called on it. For example, if previously your extract system looked like: ```rust fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) { for cloud in clouds.iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` the new version would be: ```rust fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) { for cloud in clouds.value().iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` The diff is: ```diff --- a/src/clouds.rs +++ b/src/clouds.rs @@ -1,5 +1,5 @@ -fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) { - for cloud in clouds.iter() { +fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) { + for cloud in clouds.value().iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` You can now also access resources from the render world using the normal system parameters during `Extract`: ```rust fn extract_assets(mut render_assets: ResMut<MyAssets>, source_assets: Extract<Res<MyAssets>>) { *render_assets = source_assets.clone(); } ``` Please note that all existing extract systems need to be updated to match this new style; even if they currently compile they will not run as expected. A warning will be emitted on a best-effort basis if this is not met. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective - Extracting resources currently always uses commands, which requires *at least* one additional move of the extracted value, as well as dynamic dispatch. - Addresses bevyengine#4402 (comment) ## Solution - Write the resource into a `ResMut<R>` directly. - Fall-back to commands if the resource hasn't been added yet.
# Objective - Currently, the `Extract` `RenderStage` is executed on the main world, with the render world available as a resource. - However, when needing access to resources in the render world (e.g. to mutate them), the only way to do so was to get exclusive access to the whole `RenderWorld` resource. - This meant that effectively only one extract which wrote to resources could run at a time. - We didn't previously make `Extract`ing writing to the world a non-happy path, even though we want to discourage that. ## Solution - Move the extract stage to run on the render world. - Add the main world as a `MainWorld` resource. - Add an `Extract` `SystemParam` as a convenience to access a (read only) `SystemParam` in the main world during `Extract`. ## Future work It should be possible to avoid needing to use `get_or_spawn` for the render commands, since now the `Commands`' `Entities` matches up with the world being executed on. We need to determine how this interacts with bevyengine#3519 It's theoretically possible to remove the need for the `value` method on `Extract`. However, that requires slightly changing the `SystemParam` interface, which would make it more complicated. That would probably mess up the `SystemState` api too. ## Todo I still need to add doc comments to `Extract`. --- ## Changelog ### Changed - The `Extract` `RenderStage` now runs on the render world (instead of the main world as before). You must use the `Extract` `SystemParam` to access the main world during the extract phase. Resources on the render world can now be accessed using `ResMut` during extract. ### Removed - `Commands::spawn_and_forget`. Use `Commands::get_or_spawn(e).insert_bundle(bundle)` instead ## Migration Guide The `Extract` `RenderStage` now runs on the render world (instead of the main world as before). You must use the `Extract` `SystemParam` to access the main world during the extract phase. `Extract` takes a single type parameter, which is any system parameter (such as `Res`, `Query` etc.). It will extract this from the main world, and returns the result of this extraction when `value` is called on it. For example, if previously your extract system looked like: ```rust fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) { for cloud in clouds.iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` the new version would be: ```rust fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) { for cloud in clouds.value().iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` The diff is: ```diff --- a/src/clouds.rs +++ b/src/clouds.rs @@ -1,5 +1,5 @@ -fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) { - for cloud in clouds.iter() { +fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) { + for cloud in clouds.value().iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` You can now also access resources from the render world using the normal system parameters during `Extract`: ```rust fn extract_assets(mut render_assets: ResMut<MyAssets>, source_assets: Extract<Res<MyAssets>>) { *render_assets = source_assets.clone(); } ``` Please note that all existing extract systems need to be updated to match this new style; even if they currently compile they will not run as expected. A warning will be emitted on a best-effort basis if this is not met. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective - Extracting resources currently always uses commands, which requires *at least* one additional move of the extracted value, as well as dynamic dispatch. - Addresses bevyengine#4402 (comment) ## Solution - Write the resource into a `ResMut<R>` directly. - Fall-back to commands if the resource hasn't been added yet.
# Objective Following #4402, extract systems run on the render world instead of the main world, and allow retained state operations on it's resources. We're currently extracting to `ExtractedJoints` and then copying it twice during Prepare. Once into `SkinnedMeshJoints` and again into the actual GPU buffer. This makes #4902 obsolete. ## Solution Cut out the middle copy and directly extract joints into `SkinnedMeshJoints` and remove `ExtractedJoints` entirely. This also removes the per-frame allocation that is being made to send `ExtractedJoints` into the render world. ## Performance On my local machine, this halves the time for `prepare_skinned _meshes` on `many_foxes` (195.75us -> 93.93us on average). ![image](https://user-images.githubusercontent.com/3137680/205427455-ab91a8a3-a6b0-4f0a-bd48-e54482c563b2.png) --- ## Changelog Added: `BufferVec::truncate` Added: `BufferVec::extend` Changed: `SkinnedMeshJoints::build` now takes a `&mut BufferVec` instead of a `&mut Vec` as a parameter. Removed: `ExtractedJoints`. ## Migration Guide `ExtractedJoints` has been removed. Read the bound bones from `SkinnedMeshJoints` instead.
# Objective Following #4402, extract systems run on the render world instead of the main world, and allow retained state operations on it's resources. We're currently extracting to `ExtractedJoints` and then copying it twice during Prepare. Once into `SkinnedMeshJoints` and again into the actual GPU buffer. This makes #4902 obsolete. ## Solution Cut out the middle copy and directly extract joints into `SkinnedMeshJoints` and remove `ExtractedJoints` entirely. This also removes the per-frame allocation that is being made to send `ExtractedJoints` into the render world. ## Performance On my local machine, this halves the time for `prepare_skinned _meshes` on `many_foxes` (195.75us -> 93.93us on average). ![image](https://user-images.githubusercontent.com/3137680/205427455-ab91a8a3-a6b0-4f0a-bd48-e54482c563b2.png) --- ## Changelog Added: `BufferVec::truncate` Added: `BufferVec::extend` Changed: `SkinnedMeshJoints::build` now takes a `&mut BufferVec` instead of a `&mut Vec` as a parameter. Removed: `ExtractedJoints`. ## Migration Guide `ExtractedJoints` has been removed. Read the bound bones from `SkinnedMeshJoints` instead.
# Objective Following #4402, extract systems run on the render world instead of the main world, and allow retained state operations on it's resources. We're currently extracting to `ExtractedJoints` and then copying it twice during Prepare. Once into `SkinnedMeshJoints` and again into the actual GPU buffer. This makes #4902 obsolete. ## Solution Cut out the middle copy and directly extract joints into `SkinnedMeshJoints` and remove `ExtractedJoints` entirely. This also removes the per-frame allocation that is being made to send `ExtractedJoints` into the render world. ## Performance On my local machine, this halves the time for `prepare_skinned _meshes` on `many_foxes` (195.75us -> 93.93us on average). ![image](https://user-images.githubusercontent.com/3137680/205427455-ab91a8a3-a6b0-4f0a-bd48-e54482c563b2.png) --- ## Changelog Added: `BufferVec::truncate` Added: `BufferVec::extend` Changed: `SkinnedMeshJoints::build` now takes a `&mut BufferVec` instead of a `&mut Vec` as a parameter. Removed: `ExtractedJoints`. ## Migration Guide `ExtractedJoints` has been removed. Read the bound bones from `SkinnedMeshJoints` instead.
# Objective Following #4402, extract systems run on the render world instead of the main world, and allow retained state operations on it's resources. We're currently extracting to `ExtractedJoints` and then copying it twice during Prepare. Once into `SkinnedMeshJoints` and again into the actual GPU buffer. This makes #4902 obsolete. ## Solution Cut out the middle copy and directly extract joints into `SkinnedMeshJoints` and remove `ExtractedJoints` entirely. This also removes the per-frame allocation that is being made to send `ExtractedJoints` into the render world. ## Performance On my local machine, this halves the time for `prepare_skinned _meshes` on `many_foxes` (195.75us -> 93.93us on average). ![image](https://user-images.githubusercontent.com/3137680/205427455-ab91a8a3-a6b0-4f0a-bd48-e54482c563b2.png) --- ## Changelog Added: `BufferVec::truncate` Added: `BufferVec::extend` Changed: `SkinnedMeshJoints::build` now takes a `&mut BufferVec` instead of a `&mut Vec` as a parameter. Removed: `ExtractedJoints`. ## Migration Guide `ExtractedJoints` has been removed. Read the bound bones from `SkinnedMeshJoints` instead.
# Objective Following #4402, extract systems run on the render world instead of the main world, and allow retained state operations on it's resources. We're currently extracting to `ExtractedJoints` and then copying it twice during Prepare. Once into `SkinnedMeshJoints` and again into the actual GPU buffer. This makes #4902 obsolete. ## Solution Cut out the middle copy and directly extract joints into `SkinnedMeshJoints` and remove `ExtractedJoints` entirely. This also removes the per-frame allocation that is being made to send `ExtractedJoints` into the render world. ## Performance On my local machine, this halves the time for `prepare_skinned _meshes` on `many_foxes` (195.75us -> 93.93us on average). ![image](https://user-images.githubusercontent.com/3137680/205427455-ab91a8a3-a6b0-4f0a-bd48-e54482c563b2.png) --- ## Changelog Added: `BufferVec::truncate` Added: `BufferVec::extend` Changed: `SkinnedMeshJoints::build` now takes a `&mut BufferVec` instead of a `&mut Vec` as a parameter. Removed: `ExtractedJoints`. ## Migration Guide `ExtractedJoints` has been removed. Read the bound bones from `SkinnedMeshJoints` instead.
# Objective Following bevyengine#4402, extract systems run on the render world instead of the main world, and allow retained state operations on it's resources. We're currently extracting to `ExtractedJoints` and then copying it twice during Prepare. Once into `SkinnedMeshJoints` and again into the actual GPU buffer. This makes bevyengine#4902 obsolete. ## Solution Cut out the middle copy and directly extract joints into `SkinnedMeshJoints` and remove `ExtractedJoints` entirely. This also removes the per-frame allocation that is being made to send `ExtractedJoints` into the render world. ## Performance On my local machine, this halves the time for `prepare_skinned _meshes` on `many_foxes` (195.75us -> 93.93us on average). ![image](https://user-images.githubusercontent.com/3137680/205427455-ab91a8a3-a6b0-4f0a-bd48-e54482c563b2.png) --- ## Changelog Added: `BufferVec::truncate` Added: `BufferVec::extend` Changed: `SkinnedMeshJoints::build` now takes a `&mut BufferVec` instead of a `&mut Vec` as a parameter. Removed: `ExtractedJoints`. ## Migration Guide `ExtractedJoints` has been removed. Read the bound bones from `SkinnedMeshJoints` instead.
# Objective - Currently, the `Extract` `RenderStage` is executed on the main world, with the render world available as a resource. - However, when needing access to resources in the render world (e.g. to mutate them), the only way to do so was to get exclusive access to the whole `RenderWorld` resource. - This meant that effectively only one extract which wrote to resources could run at a time. - We didn't previously make `Extract`ing writing to the world a non-happy path, even though we want to discourage that. ## Solution - Move the extract stage to run on the render world. - Add the main world as a `MainWorld` resource. - Add an `Extract` `SystemParam` as a convenience to access a (read only) `SystemParam` in the main world during `Extract`. ## Future work It should be possible to avoid needing to use `get_or_spawn` for the render commands, since now the `Commands`' `Entities` matches up with the world being executed on. We need to determine how this interacts with bevyengine#3519 It's theoretically possible to remove the need for the `value` method on `Extract`. However, that requires slightly changing the `SystemParam` interface, which would make it more complicated. That would probably mess up the `SystemState` api too. ## Todo I still need to add doc comments to `Extract`. --- ## Changelog ### Changed - The `Extract` `RenderStage` now runs on the render world (instead of the main world as before). You must use the `Extract` `SystemParam` to access the main world during the extract phase. Resources on the render world can now be accessed using `ResMut` during extract. ### Removed - `Commands::spawn_and_forget`. Use `Commands::get_or_spawn(e).insert_bundle(bundle)` instead ## Migration Guide The `Extract` `RenderStage` now runs on the render world (instead of the main world as before). You must use the `Extract` `SystemParam` to access the main world during the extract phase. `Extract` takes a single type parameter, which is any system parameter (such as `Res`, `Query` etc.). It will extract this from the main world, and returns the result of this extraction when `value` is called on it. For example, if previously your extract system looked like: ```rust fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) { for cloud in clouds.iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` the new version would be: ```rust fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) { for cloud in clouds.value().iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` The diff is: ```diff --- a/src/clouds.rs +++ b/src/clouds.rs @@ -1,5 +1,5 @@ -fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) { - for cloud in clouds.iter() { +fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) { + for cloud in clouds.value().iter() { commands.get_or_spawn(cloud).insert(Cloud); } } ``` You can now also access resources from the render world using the normal system parameters during `Extract`: ```rust fn extract_assets(mut render_assets: ResMut<MyAssets>, source_assets: Extract<Res<MyAssets>>) { *render_assets = source_assets.clone(); } ``` Please note that all existing extract systems need to be updated to match this new style; even if they currently compile they will not run as expected. A warning will be emitted on a best-effort basis if this is not met. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective - Extracting resources currently always uses commands, which requires *at least* one additional move of the extracted value, as well as dynamic dispatch. - Addresses bevyengine#4402 (comment) ## Solution - Write the resource into a `ResMut<R>` directly. - Fall-back to commands if the resource hasn't been added yet.
# Objective Following bevyengine#4402, extract systems run on the render world instead of the main world, and allow retained state operations on it's resources. We're currently extracting to `ExtractedJoints` and then copying it twice during Prepare. Once into `SkinnedMeshJoints` and again into the actual GPU buffer. This makes bevyengine#4902 obsolete. ## Solution Cut out the middle copy and directly extract joints into `SkinnedMeshJoints` and remove `ExtractedJoints` entirely. This also removes the per-frame allocation that is being made to send `ExtractedJoints` into the render world. ## Performance On my local machine, this halves the time for `prepare_skinned _meshes` on `many_foxes` (195.75us -> 93.93us on average). ![image](https://user-images.githubusercontent.com/3137680/205427455-ab91a8a3-a6b0-4f0a-bd48-e54482c563b2.png) --- ## Changelog Added: `BufferVec::truncate` Added: `BufferVec::extend` Changed: `SkinnedMeshJoints::build` now takes a `&mut BufferVec` instead of a `&mut Vec` as a parameter. Removed: `ExtractedJoints`. ## Migration Guide `ExtractedJoints` has been removed. Read the bound bones from `SkinnedMeshJoints` instead.
Required for bevyengine#4402. # Objective - derived `SystemParam` implementations were never `ReadOnlySystemParamFetch` - We want them to be, e.g. for `EventReader` ## Solution - If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
Objective
Extract
RenderStage
is executed on the main world, with the render world available as a resource.RenderWorld
resource.Extract
ing writing to the world a non-happy path, even though we want to discourage that.Solution
MainWorld
resource.Extract
SystemParam
as a convenience to access a (read only)SystemParam
in the main world duringExtract
.Future work
It should be possible to avoid needing to use
get_or_spawn
for the render commands, since now theCommands
'Entities
matches up with the world being executed on.We need to determine how this interacts with #3519
It's theoretically possible to remove the need for the
value
method onExtract
. However, that requires slightly changing theSystemParam
interface, which would make it more complicated. That would probably mess up theSystemState
api too.Todo
I still need to add doc comments to
Extract
.Changelog
Changed
Extract
RenderStage
now runs on the render world (instead of the main world as before).You must use the
Extract
SystemParam
to access the main world during the extract phase.Resources on the render world can now be accessed using
ResMut
during extract.Removed
Commands::spawn_and_forget
. UseCommands::get_or_spawn(e).insert_bundle(bundle)
insteadMigration Guide
The
Extract
RenderStage
now runs on the render world (instead of the main world as before).You must use the
Extract
SystemParam
to access the main world during the extract phase.Extract
takes a single type parameter, which is any system parameter (such asRes
,Query
etc.). It will extract this from the main world, and returns the result of this extraction whenvalue
is called on it.For example, if previously your extract system looked like:
the new version would be:
The diff is:
You can now also access resources from the render world using the normal system parameters during
Extract
:Please note that all existing extract systems need to be updated to match this new style; even if they currently compile they will not run as expected. A warning will be emitted on a best-effort basis if this is not met.