Parallelize bevy 0.16-rc bottlenecks (#18632)
# Objective - Found stuttering and performance degradation while updating big_space stress tests. ## Solution - Identify and fix slow spots using tracy. Patch to verify fixes. ## Testing - Tracy - Before:  - prev_gt parallelization and mutating instead of component insertion:  - parallelize visibility ranges and mesh specialization  --------- Co-authored-by: Zachary Harrold <zac@harrold.com.au>
This commit is contained in:
parent
d5c5de20b1
commit
cba6698033
@ -52,6 +52,7 @@ use bevy_render::{
|
|||||||
};
|
};
|
||||||
use bevy_render::{mesh::allocator::MeshAllocator, sync_world::MainEntityHashMap};
|
use bevy_render::{mesh::allocator::MeshAllocator, sync_world::MainEntityHashMap};
|
||||||
use bevy_render::{texture::FallbackImage, view::RenderVisibleEntities};
|
use bevy_render::{texture::FallbackImage, view::RenderVisibleEntities};
|
||||||
|
use bevy_utils::Parallel;
|
||||||
use core::{hash::Hash, marker::PhantomData};
|
use core::{hash::Hash, marker::PhantomData};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
@ -832,14 +833,18 @@ pub fn check_entities_needing_specialization<M>(
|
|||||||
With<MeshMaterial3d<M>>,
|
With<MeshMaterial3d<M>>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
|
mut par_local: Local<Parallel<Vec<Entity>>>,
|
||||||
mut entities_needing_specialization: ResMut<EntitiesNeedingSpecialization<M>>,
|
mut entities_needing_specialization: ResMut<EntitiesNeedingSpecialization<M>>,
|
||||||
) where
|
) where
|
||||||
M: Material,
|
M: Material,
|
||||||
{
|
{
|
||||||
entities_needing_specialization.clear();
|
entities_needing_specialization.clear();
|
||||||
for entity in &needs_specialization {
|
|
||||||
entities_needing_specialization.push(entity);
|
needs_specialization
|
||||||
}
|
.par_iter()
|
||||||
|
.for_each(|entity| par_local.borrow_local_mut().push(entity));
|
||||||
|
|
||||||
|
par_local.drain_into(&mut entities_needing_specialization);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn specialize_material_meshes<M: Material>(
|
pub fn specialize_material_meshes<M: Material>(
|
||||||
|
@ -268,20 +268,22 @@ type PreviousMeshFilter = Or<(With<Mesh3d>, With<MeshletMesh3d>)>;
|
|||||||
pub fn update_mesh_previous_global_transforms(
|
pub fn update_mesh_previous_global_transforms(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
views: Query<&Camera, Or<(With<Camera3d>, With<ShadowView>)>>,
|
views: Query<&Camera, Or<(With<Camera3d>, With<ShadowView>)>>,
|
||||||
meshes: Query<(Entity, &GlobalTransform, Option<&PreviousGlobalTransform>), PreviousMeshFilter>,
|
new_meshes: Query<
|
||||||
|
(Entity, &GlobalTransform),
|
||||||
|
(PreviousMeshFilter, Without<PreviousGlobalTransform>),
|
||||||
|
>,
|
||||||
|
mut meshes: Query<(&GlobalTransform, &mut PreviousGlobalTransform), PreviousMeshFilter>,
|
||||||
) {
|
) {
|
||||||
let should_run = views.iter().any(|camera| camera.is_active);
|
let should_run = views.iter().any(|camera| camera.is_active);
|
||||||
|
|
||||||
if should_run {
|
if should_run {
|
||||||
for (entity, transform, old_previous_transform) in &meshes {
|
for (entity, transform) in &new_meshes {
|
||||||
let new_previous_transform = PreviousGlobalTransform(transform.affine());
|
let new_previous_transform = PreviousGlobalTransform(transform.affine());
|
||||||
// Make sure not to trigger change detection on
|
|
||||||
// `PreviousGlobalTransform` if the previous transform hasn't
|
|
||||||
// changed.
|
|
||||||
if old_previous_transform != Some(&new_previous_transform) {
|
|
||||||
commands.entity(entity).try_insert(new_previous_transform);
|
commands.entity(entity).try_insert(new_previous_transform);
|
||||||
}
|
}
|
||||||
}
|
meshes.par_iter_mut().for_each(|(transform, mut previous)| {
|
||||||
|
previous.set_if_neq(PreviousGlobalTransform(transform.affine()));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,13 +15,13 @@ use bevy_ecs::{
|
|||||||
removal_detection::RemovedComponents,
|
removal_detection::RemovedComponents,
|
||||||
resource::Resource,
|
resource::Resource,
|
||||||
schedule::IntoScheduleConfigs as _,
|
schedule::IntoScheduleConfigs as _,
|
||||||
system::{Query, Res, ResMut},
|
system::{Local, Query, Res, ResMut},
|
||||||
};
|
};
|
||||||
use bevy_math::{vec4, FloatOrd, Vec4};
|
use bevy_math::{vec4, FloatOrd, Vec4};
|
||||||
use bevy_platform_support::collections::HashMap;
|
use bevy_platform_support::collections::HashMap;
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use bevy_transform::components::GlobalTransform;
|
use bevy_transform::components::GlobalTransform;
|
||||||
use bevy_utils::prelude::default;
|
use bevy_utils::{prelude::default, Parallel};
|
||||||
use nonmax::NonMaxU16;
|
use nonmax::NonMaxU16;
|
||||||
use wgpu::{BufferBindingType, BufferUsages};
|
use wgpu::{BufferBindingType, BufferUsages};
|
||||||
|
|
||||||
@ -385,7 +385,8 @@ impl VisibleEntityRanges {
|
|||||||
pub fn check_visibility_ranges(
|
pub fn check_visibility_ranges(
|
||||||
mut visible_entity_ranges: ResMut<VisibleEntityRanges>,
|
mut visible_entity_ranges: ResMut<VisibleEntityRanges>,
|
||||||
view_query: Query<(Entity, &GlobalTransform), With<Camera>>,
|
view_query: Query<(Entity, &GlobalTransform), With<Camera>>,
|
||||||
mut entity_query: Query<(Entity, &GlobalTransform, Option<&Aabb>, &VisibilityRange)>,
|
mut par_local: Local<Parallel<Vec<(Entity, u32)>>>,
|
||||||
|
entity_query: Query<(Entity, &GlobalTransform, Option<&Aabb>, &VisibilityRange)>,
|
||||||
) {
|
) {
|
||||||
visible_entity_ranges.clear();
|
visible_entity_ranges.clear();
|
||||||
|
|
||||||
@ -404,7 +405,8 @@ pub fn check_visibility_ranges(
|
|||||||
|
|
||||||
// Check each entity/view pair. Only consider entities with
|
// Check each entity/view pair. Only consider entities with
|
||||||
// [`VisibilityRange`] components.
|
// [`VisibilityRange`] components.
|
||||||
for (entity, entity_transform, maybe_model_aabb, visibility_range) in entity_query.iter_mut() {
|
entity_query.par_iter().for_each(
|
||||||
|
|(entity, entity_transform, maybe_model_aabb, visibility_range)| {
|
||||||
let mut visibility = 0;
|
let mut visibility = 0;
|
||||||
for (view_index, &(_, view_position)) in views.iter().enumerate() {
|
for (view_index, &(_, view_position)) in views.iter().enumerate() {
|
||||||
// If instructed to use the AABB and the model has one, use its
|
// If instructed to use the AABB and the model has one, use its
|
||||||
@ -425,9 +427,12 @@ pub fn check_visibility_ranges(
|
|||||||
// Invisible entities have no entry at all in the hash map. This speeds
|
// Invisible entities have no entry at all in the hash map. This speeds
|
||||||
// up checks slightly in this common case.
|
// up checks slightly in this common case.
|
||||||
if visibility != 0 {
|
if visibility != 0 {
|
||||||
visible_entity_ranges.entities.insert(entity, visibility);
|
par_local.borrow_local_mut().push((entity, visibility));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
visible_entity_ranges.entities.extend(par_local.drain());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extracts all [`VisibilityRange`] components from the main world to the
|
/// Extracts all [`VisibilityRange`] components from the main world to the
|
||||||
|
@ -45,6 +45,7 @@ use bevy_render::{
|
|||||||
view::{ExtractedView, ViewVisibility},
|
view::{ExtractedView, ViewVisibility},
|
||||||
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
|
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
|
||||||
};
|
};
|
||||||
|
use bevy_utils::Parallel;
|
||||||
use core::{hash::Hash, marker::PhantomData};
|
use core::{hash::Hash, marker::PhantomData};
|
||||||
use derive_more::derive::From;
|
use derive_more::derive::From;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
@ -660,14 +661,18 @@ pub fn check_entities_needing_specialization<M>(
|
|||||||
With<MeshMaterial2d<M>>,
|
With<MeshMaterial2d<M>>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
|
mut par_local: Local<Parallel<Vec<Entity>>>,
|
||||||
mut entities_needing_specialization: ResMut<EntitiesNeedingSpecialization<M>>,
|
mut entities_needing_specialization: ResMut<EntitiesNeedingSpecialization<M>>,
|
||||||
) where
|
) where
|
||||||
M: Material2d,
|
M: Material2d,
|
||||||
{
|
{
|
||||||
entities_needing_specialization.clear();
|
entities_needing_specialization.clear();
|
||||||
for entity in &needs_specialization {
|
|
||||||
entities_needing_specialization.push(entity);
|
needs_specialization
|
||||||
}
|
.par_iter()
|
||||||
|
.for_each(|entity| par_local.borrow_local_mut().push(entity));
|
||||||
|
|
||||||
|
par_local.drain_into(&mut entities_needing_specialization);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn specialize_material2d_meshes<M: Material2d>(
|
pub fn specialize_material2d_meshes<M: Material2d>(
|
||||||
|
Loading…
Reference in New Issue
Block a user