Skip to content

Commit

Permalink
Revert "bevy_pbr: Leverage ComputeTaskPool parallelism for assign_lig…
Browse files Browse the repository at this point in the history
…hts_to_clusters"

This kind of optimisation is more controversial so I think it should at least
be part of a separate PR.

This reverts commit 14b6f0a.
  • Loading branch information
superdump committed Feb 25, 2022
1 parent 867a368 commit 4385a7a
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 109 deletions.
1 change: 0 additions & 1 deletion crates/bevy_pbr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.6.0" }
bevy_math = { path = "../bevy_math", version = "0.6.0" }
bevy_reflect = { path = "../bevy_reflect", version = "0.6.0", features = ["bevy"] }
bevy_render = { path = "../bevy_render", version = "0.6.0" }
bevy_tasks = { path = "../bevy_tasks", version = "0.6.0" }
bevy_transform = { path = "../bevy_transform", version = "0.6.0" }
bevy_utils = { path = "../bevy_utils", version = "0.6.0" }
bevy_window = { path = "../bevy_window", version = "0.6.0" }
Expand Down
200 changes: 92 additions & 108 deletions crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use bevy_render::{
primitives::{Aabb, CubemapFrusta, Frustum, Sphere},
view::{ComputedVisibility, RenderLayers, Visibility, VisibleEntities},
};
use bevy_tasks::ComputeTaskPool;
use bevy_transform::components::GlobalTransform;
use bevy_window::Windows;

Expand Down Expand Up @@ -486,7 +485,6 @@ fn cluster_to_index(cluster_dimensions: UVec3, cluster: UVec3) -> usize {
// NOTE: Run this before update_point_light_frusta!
pub fn assign_lights_to_clusters(
mut commands: Commands,
task_pool: Res<ComputeTaskPool>,
mut global_lights: ResMut<VisiblePointLights>,
mut views: Query<(Entity, &GlobalTransform, &Camera, &Frustum, &mut Clusters)>,
lights: Query<(Entity, &GlobalTransform, &PointLight)>,
Expand All @@ -510,116 +508,102 @@ pub fn assign_lights_to_clusters(
vec![VisiblePointLights::from_light_count(light_count); cluster_count];
let mut visible_lights_set = HashSet::with_capacity(light_count);

let lights_vec = lights.iter().collect::<Vec<_>>();
let indices_entities = task_pool.scope(|scope| {
let clusters = &*clusters;
for chunk in lights_vec.chunks(32) {
scope.spawn(async move {
let mut indices_entities = Vec::new();
for (light_entity, light_transform, light) in chunk {
let light_sphere = Sphere {
center: light_transform.translation,
radius: light.range,
};

// Check if the light is within the view frustum
if !frustum.intersects_sphere(&light_sphere) {
continue;
}
for (light_entity, light_transform, light) in lights.iter() {
let light_sphere = Sphere {
center: light_transform.translation,
radius: light.range,
};

// Calculate an AABB for the light in view space, find the corresponding clusters for the min and max
// points of the AABB, then iterate over just those clusters for this light
let light_aabb_view = Aabb {
center: (inverse_view_transform * light_sphere.center.extend(1.0))
.xyz(),
half_extents: Vec3::splat(light_sphere.radius),
};
let (light_aabb_view_min, light_aabb_view_max) =
(light_aabb_view.min(), light_aabb_view.max());
// Is there a cheaper way to do this? The problem is that because of perspective
// the point at max z but min xy may be less xy in screenspace, and similar. As
// such, projecting the min and max xy at both the closer and further z and taking
// the min and max of those projected points addresses this.
let (
light_aabb_view_xymin_near,
light_aabb_view_xymin_far,
light_aabb_view_xymax_near,
light_aabb_view_xymax_far,
) = (
light_aabb_view_min,
light_aabb_view_min.xy().extend(light_aabb_view_max.z),
light_aabb_view_max.xy().extend(light_aabb_view_min.z),
light_aabb_view_max,
);
let (
light_aabb_clip_xymin_near,
light_aabb_clip_xymin_far,
light_aabb_clip_xymax_near,
light_aabb_clip_xymax_far,
) = (
camera.projection_matrix * light_aabb_view_xymin_near.extend(1.0),
camera.projection_matrix * light_aabb_view_xymin_far.extend(1.0),
camera.projection_matrix * light_aabb_view_xymax_near.extend(1.0),
camera.projection_matrix * light_aabb_view_xymax_far.extend(1.0),
);
let (
light_aabb_ndc_xymin_near,
light_aabb_ndc_xymin_far,
light_aabb_ndc_xymax_near,
light_aabb_ndc_xymax_far,
) = (
light_aabb_clip_xymin_near.xyz() / light_aabb_clip_xymin_near.w,
light_aabb_clip_xymin_far.xyz() / light_aabb_clip_xymin_far.w,
light_aabb_clip_xymax_near.xyz() / light_aabb_clip_xymax_near.w,
light_aabb_clip_xymax_far.xyz() / light_aabb_clip_xymax_far.w,
);
let (light_aabb_ndc_min, light_aabb_ndc_max) = (
light_aabb_ndc_xymin_near
.min(light_aabb_ndc_xymin_far)
.min(light_aabb_ndc_xymax_near)
.min(light_aabb_ndc_xymax_far),
light_aabb_ndc_xymin_near
.max(light_aabb_ndc_xymin_far)
.max(light_aabb_ndc_xymax_near)
.max(light_aabb_ndc_xymax_far),
);
let min_cluster = ndc_position_to_cluster(
clusters.axis_slices,
cluster_factors,
is_orthographic,
light_aabb_ndc_min,
light_aabb_view_min.z,
);
let max_cluster = ndc_position_to_cluster(
clusters.axis_slices,
cluster_factors,
is_orthographic,
light_aabb_ndc_max,
light_aabb_view_max.z,
);
let (min_cluster, max_cluster) =
(min_cluster.min(max_cluster), min_cluster.max(max_cluster));
for y in min_cluster.y..=max_cluster.y {
for x in min_cluster.x..=max_cluster.x {
for z in min_cluster.z..=max_cluster.z {
let cluster_index =
cluster_to_index(clusters.axis_slices, UVec3::new(x, y, z));
let cluster_aabb = &clusters.aabbs[cluster_index];
if light_sphere.intersects_obb(cluster_aabb, &view_transform) {
indices_entities.push((cluster_index, *light_entity));
}
}
}
// Check if the light is within the view frustum
if !frustum.intersects_sphere(&light_sphere) {
continue;
}

// Calculate an AABB for the light in view space, find the corresponding clusters for the min and max
// points of the AABB, then iterate over just those clusters for this light
let light_aabb_view = Aabb {
center: (inverse_view_transform * light_sphere.center.extend(1.0)).xyz(),
half_extents: Vec3::splat(light_sphere.radius),
};
let (light_aabb_view_min, light_aabb_view_max) =
(light_aabb_view.min(), light_aabb_view.max());
// Is there a cheaper way to do this? The problem is that because of perspective
// the point at max z but min xy may be less xy in screenspace, and similar. As
// such, projecting the min and max xy at both the closer and further z and taking
// the min and max of those projected points addresses this.
let (
light_aabb_view_xymin_near,
light_aabb_view_xymin_far,
light_aabb_view_xymax_near,
light_aabb_view_xymax_far,
) = (
light_aabb_view_min,
light_aabb_view_min.xy().extend(light_aabb_view_max.z),
light_aabb_view_max.xy().extend(light_aabb_view_min.z),
light_aabb_view_max,
);
let (
light_aabb_clip_xymin_near,
light_aabb_clip_xymin_far,
light_aabb_clip_xymax_near,
light_aabb_clip_xymax_far,
) = (
camera.projection_matrix * light_aabb_view_xymin_near.extend(1.0),
camera.projection_matrix * light_aabb_view_xymin_far.extend(1.0),
camera.projection_matrix * light_aabb_view_xymax_near.extend(1.0),
camera.projection_matrix * light_aabb_view_xymax_far.extend(1.0),
);
let (
light_aabb_ndc_xymin_near,
light_aabb_ndc_xymin_far,
light_aabb_ndc_xymax_near,
light_aabb_ndc_xymax_far,
) = (
light_aabb_clip_xymin_near.xyz() / light_aabb_clip_xymin_near.w,
light_aabb_clip_xymin_far.xyz() / light_aabb_clip_xymin_far.w,
light_aabb_clip_xymax_near.xyz() / light_aabb_clip_xymax_near.w,
light_aabb_clip_xymax_far.xyz() / light_aabb_clip_xymax_far.w,
);
let (light_aabb_ndc_min, light_aabb_ndc_max) = (
light_aabb_ndc_xymin_near
.min(light_aabb_ndc_xymin_far)
.min(light_aabb_ndc_xymax_near)
.min(light_aabb_ndc_xymax_far),
light_aabb_ndc_xymin_near
.max(light_aabb_ndc_xymin_far)
.max(light_aabb_ndc_xymax_near)
.max(light_aabb_ndc_xymax_far),
);
let min_cluster = ndc_position_to_cluster(
clusters.axis_slices,
cluster_factors,
is_orthographic,
light_aabb_ndc_min,
light_aabb_view_min.z,
);
let max_cluster = ndc_position_to_cluster(
clusters.axis_slices,
cluster_factors,
is_orthographic,
light_aabb_ndc_max,
light_aabb_view_max.z,
);
let (min_cluster, max_cluster) =
(min_cluster.min(max_cluster), min_cluster.max(max_cluster));
for y in min_cluster.y..=max_cluster.y {
for x in min_cluster.x..=max_cluster.x {
for z in min_cluster.z..=max_cluster.z {
let cluster_index =
cluster_to_index(clusters.axis_slices, UVec3::new(x, y, z));
let cluster_aabb = &clusters.aabbs[cluster_index];
if light_sphere.intersects_obb(cluster_aabb, &view_transform) {
global_lights_set.insert(light_entity);
visible_lights_set.insert(light_entity);
clusters_lights[cluster_index].entities.push(light_entity);
}
}
indices_entities
});
}
}
});
for (cluster_index, light_entity) in indices_entities.into_iter().flatten() {
global_lights_set.insert(light_entity);
visible_lights_set.insert(light_entity);
clusters_lights[cluster_index].entities.push(light_entity);
}

for cluster_lights in &mut clusters_lights {
Expand Down

0 comments on commit 4385a7a

Please sign in to comment.