mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 22:50:19 +00:00
Change check_visibility to use thread-local queues instead of a channel (#4663)
# Objective Further speed up visibility checking by removing the main sources of contention for the system. ## Solution - ~~Make `ComputedVisibility` a resource wrapping a `FixedBitset`.~~ - ~~Remove `ComputedVisibility` as a component.~~ ~~This adds a one-bit overhead to every entity in the app world. For a game with 100,000 entities, this is 12.5KB of memory. This is still small enough to fit entirely in most L1 caches. Also removes the need for a per-Entity change detection tick. This reduces the memory footprint of ComputedVisibility 72x.~~ ~~The decreased memory usage and less fragmented memory locality should provide significant performance benefits.~~ ~~Clearing visible entities should be significantly faster than before:~~ - ~~Setting one `u32` to 0 clears 32 entities per cycle.~~ - ~~No archetype fragmentation to contend with.~~ - ~~Change detection is applied to the resource, so there is no per-Entity update tick requirement.~~ ~~The side benefit of this design is that it removes one more "computed component" from userspace. Though accessing the values within it are now less ergonomic.~~ This PR changes `crossbeam_channel` in `check_visibility` to use a `Local<ThreadLocal<Cell<Vec<Entity>>>` to mark down visible entities instead. Co-Authored-By: TheRawMeatball <therawmeatball@gmail.com> Co-Authored-By: Aevyrie <aevyrie@gmail.com>
This commit is contained in:
parent
511bcc9633
commit
389df18343
2 changed files with 31 additions and 17 deletions
|
@ -54,9 +54,9 @@ bitflags = "1.2.1"
|
||||||
smallvec = { version = "1.6", features = ["union", "const_generics"] }
|
smallvec = { version = "1.6", features = ["union", "const_generics"] }
|
||||||
once_cell = "1.4.1" # TODO: replace once_cell with std equivalent if/when this lands: https://github.com/rust-lang/rfcs/pull/2788
|
once_cell = "1.4.1" # TODO: replace once_cell with std equivalent if/when this lands: https://github.com/rust-lang/rfcs/pull/2788
|
||||||
downcast-rs = "1.2.0"
|
downcast-rs = "1.2.0"
|
||||||
|
thread_local = "1.1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
futures-lite = "1.4.0"
|
futures-lite = "1.4.0"
|
||||||
crossbeam-channel = "0.5.0"
|
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
hex = "0.4.2"
|
hex = "0.4.2"
|
||||||
hexasphere = "7.0.0"
|
hexasphere = "7.0.0"
|
||||||
|
|
|
@ -10,6 +10,8 @@ use bevy_reflect::std_traits::ReflectDefault;
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use bevy_transform::components::GlobalTransform;
|
use bevy_transform::components::GlobalTransform;
|
||||||
use bevy_transform::TransformSystem;
|
use bevy_transform::TransformSystem;
|
||||||
|
use std::cell::Cell;
|
||||||
|
use thread_local::ThreadLocal;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
camera::{Camera, CameraProjection, OrthographicProjection, PerspectiveProjection, Projection},
|
camera::{Camera, CameraProjection, OrthographicProjection, PerspectiveProjection, Projection},
|
||||||
|
@ -148,22 +150,30 @@ pub fn update_frusta<T: Component + CameraProjection + Send + Sync + 'static>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_visibility(
|
pub fn check_visibility(
|
||||||
|
mut thread_queues: Local<ThreadLocal<Cell<Vec<Entity>>>>,
|
||||||
mut view_query: Query<(&mut VisibleEntities, &Frustum, Option<&RenderLayers>), With<Camera>>,
|
mut view_query: Query<(&mut VisibleEntities, &Frustum, Option<&RenderLayers>), With<Camera>>,
|
||||||
mut visible_entity_query: Query<(
|
mut visible_entity_query: ParamSet<(
|
||||||
Entity,
|
Query<&mut ComputedVisibility>,
|
||||||
&Visibility,
|
Query<(
|
||||||
&mut ComputedVisibility,
|
Entity,
|
||||||
Option<&RenderLayers>,
|
&Visibility,
|
||||||
Option<&Aabb>,
|
&mut ComputedVisibility,
|
||||||
Option<&NoFrustumCulling>,
|
Option<&RenderLayers>,
|
||||||
Option<&GlobalTransform>,
|
Option<&Aabb>,
|
||||||
|
Option<&NoFrustumCulling>,
|
||||||
|
Option<&GlobalTransform>,
|
||||||
|
)>,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
|
// Reset the computed visibility to false
|
||||||
|
for mut computed_visibility in visible_entity_query.p0().iter_mut() {
|
||||||
|
computed_visibility.is_visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
for (mut visible_entities, frustum, maybe_view_mask) in view_query.iter_mut() {
|
for (mut visible_entities, frustum, maybe_view_mask) in view_query.iter_mut() {
|
||||||
let view_mask = maybe_view_mask.copied().unwrap_or_default();
|
let view_mask = maybe_view_mask.copied().unwrap_or_default();
|
||||||
let (visible_entity_sender, visible_entity_receiver) = crossbeam_channel::unbounded();
|
visible_entities.entities.clear();
|
||||||
|
visible_entity_query.p1().par_for_each_mut(
|
||||||
visible_entity_query.par_for_each_mut(
|
|
||||||
1024,
|
1024,
|
||||||
|(
|
|(
|
||||||
entity,
|
entity,
|
||||||
|
@ -174,12 +184,10 @@ pub fn check_visibility(
|
||||||
maybe_no_frustum_culling,
|
maybe_no_frustum_culling,
|
||||||
maybe_transform,
|
maybe_transform,
|
||||||
)| {
|
)| {
|
||||||
// Reset visibility
|
|
||||||
computed_visibility.is_visible = false;
|
|
||||||
|
|
||||||
if !visibility.is_visible {
|
if !visibility.is_visible {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let entity_mask = maybe_entity_mask.copied().unwrap_or_default();
|
let entity_mask = maybe_entity_mask.copied().unwrap_or_default();
|
||||||
if !view_mask.intersects(&entity_mask) {
|
if !view_mask.intersects(&entity_mask) {
|
||||||
return;
|
return;
|
||||||
|
@ -205,9 +213,15 @@ pub fn check_visibility(
|
||||||
}
|
}
|
||||||
|
|
||||||
computed_visibility.is_visible = true;
|
computed_visibility.is_visible = true;
|
||||||
visible_entity_sender.send(entity).ok();
|
let cell = thread_queues.get_or_default();
|
||||||
|
let mut queue = cell.take();
|
||||||
|
queue.push(entity);
|
||||||
|
cell.set(queue);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
visible_entities.entities = visible_entity_receiver.try_iter().collect();
|
|
||||||
|
for cell in thread_queues.iter_mut() {
|
||||||
|
visible_entities.entities.append(cell.get_mut());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue