From 3c49aabee5ccc5532ebb7998076fc6d23f9fa993 Mon Sep 17 00:00:00 2001 From: Aevyrie Roessler Date: Fri, 15 Apr 2022 15:46:09 -0700 Subject: [PATCH] run frustum cumming with parallel iterator --- crates/bevy_render/Cargo.toml | 1 + crates/bevy_render/src/camera/camera.rs | 13 +- crates/bevy_render/src/view/visibility/mod.rs | 119 +++++++++--------- 3 files changed, 68 insertions(+), 65 deletions(-) diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 33da4af7f715fc..e0a8fdf924860d 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -36,6 +36,7 @@ bevy_derive = { path = "../bevy_derive", version = "0.7.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.7.0" } bevy_math = { path = "../bevy_math", version = "0.7.0" } bevy_reflect = { path = "../bevy_reflect", version = "0.7.0", features = ["bevy"] } +bevy_tasks = { path = "../bevy_tasks", version = "0.7.0" } bevy_transform = { path = "../bevy_transform", version = "0.7.0" } bevy_window = { path = "../bevy_window", version = "0.7.0" } bevy_utils = { path = "../bevy_utils", version = "0.7.0" } diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index a69892cd22a3a1..360265a6e3afb8 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -74,12 +74,13 @@ impl RenderTarget { RenderTarget::Window(window_id) => windows .get(*window_id) .map(|window| UVec2::new(window.physical_width(), window.physical_height())), - RenderTarget::Image(image_handle) => images.get(image_handle).map(|image| { - let Extent3d { width, height, .. } = image.texture_descriptor.size; - UVec2::new(width, height) - }), - } - .filter(|size| size.x > 0 && size.y > 0) + RenderTarget::Image(image_handle) => images + .get(image_handle) + .map(|image| { + let Extent3d { width, height, .. } = image.texture_descriptor.size; + UVec2::new(width, height) + }), + }.filter(|dim| dim.x > 0 && dim.y > 0) } pub fn get_logical_size(&self, windows: &Windows, images: &Assets) -> Option { match self { diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index e7cd28c78ce613..f21f567b3172e5 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -1,6 +1,9 @@ mod render_layers; +use std::sync::Arc; + use bevy_math::Vec3A; +use parking_lot::RwLock; pub use render_layers::*; use bevy_app::{CoreStage, Plugin}; @@ -139,72 +142,70 @@ pub fn update_frusta( } pub fn check_visibility( + pool: Res, mut view_query: Query<(&mut VisibleEntities, &Frustum, Option<&RenderLayers>), With>, - mut visible_entity_query: ParamSet<( - Query<&mut ComputedVisibility>, - Query<( - Entity, - &Visibility, - &mut ComputedVisibility, - Option<&RenderLayers>, - Option<&Aabb>, - Option<&NoFrustumCulling>, - Option<&GlobalTransform>, - )>, + mut visible_entity_query: Query<( + Entity, + &Visibility, + &mut ComputedVisibility, + Option<&RenderLayers>, + 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() { visible_entities.entities.clear(); let view_mask = maybe_view_mask.copied().unwrap_or_default(); - for ( - entity, - visibility, - mut computed_visibility, - maybe_entity_mask, - maybe_aabb, - maybe_no_frustum_culling, - maybe_transform, - ) in visible_entity_query.p1().iter_mut() - { - if !visibility.is_visible { - continue; - } - - let entity_mask = maybe_entity_mask.copied().unwrap_or_default(); - if !view_mask.intersects(&entity_mask) { - continue; - } - - // If we have an aabb and transform, do frustum culling - if let (Some(model_aabb), None, Some(transform)) = - (maybe_aabb, maybe_no_frustum_culling, maybe_transform) - { - let model = transform.compute_matrix(); - let model_sphere = Sphere { - center: model.transform_point3a(model_aabb.center), - radius: (Vec3A::from(transform.scale) * model_aabb.half_extents).length(), - }; - // Do quick sphere-based frustum culling - if !frustum.intersects_sphere(&model_sphere, false) { - continue; + let viz = Arc::new(RwLock::new(Vec::new())); + + visible_entity_query.par_for_each_mut( + &pool, + 32, + move |( + entity, + visibility, + mut computed_visibility, + maybe_entity_mask, + maybe_aabb, + maybe_no_frustum_culling, + maybe_transform, + )| { + computed_visibility.is_visible = false; + if visibility.is_visible { + let entity_mask = maybe_entity_mask.copied().unwrap_or_default(); + if view_mask.intersects(&entity_mask) { + let mut skip = false; + // If we have an aabb and transform, do frustum culling + if let (Some(model_aabb), None, Some(transform)) = + (maybe_aabb, maybe_no_frustum_culling, maybe_transform) + { + let model = transform.compute_matrix(); + let model_sphere = Sphere { + center: model.transform_point3a(model_aabb.center), + radius: (Vec3A::from(transform.scale) * model_aabb.half_extents) + .length(), + }; + // Do quick sphere-based frustum culling + if !frustum.intersects_sphere(&model_sphere, false) { + skip = true; + } + // If we have an aabb, do aabb-based frustum culling + if !frustum.intersects_obb(model_aabb, &model, false) { + skip = true; + } + } + + if !skip { + computed_visibility.is_visible = true; + viz.write().push(entity); + } + } + // TODO: check for big changes in visible entities len() vs capacity() (ex: 2x) and resize + // to prevent holding unneeded memory } - // If we have an aabb, do aabb-based frustum culling - if !frustum.intersects_obb(model_aabb, &model, false) { - continue; - } - } - - computed_visibility.is_visible = true; - visible_entities.entities.push(entity); - } - - // TODO: check for big changes in visible entities len() vs capacity() (ex: 2x) and resize - // to prevent holding unneeded memory + }, + ); } }