Skip to content
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] - fix issues with too many point lights #3916

Closed
wants to merge 16 commits into from

Conversation

robtfm
Copy link
Contributor

@robtfm robtfm commented Feb 11, 2022

Objective

fix #3915

Solution

the issues are caused by

  • lights are assigned to clusters before being filtered down to MAX_POINT_LIGHTS, leading to cluster counts potentially being too high
  • after fixing the above, packing the count into 8 bits still causes overflow with exactly 256 lights affecting a cluster

to fix:

assign_lights_to_clusters

  • limit extracted lights to MAX_POINT_LIGHTS, selecting based on shadow-caster & intensity (if required)
  • warn if MAX_POINT_LIGHT count is exceeded

prepare_lights

  • limit the lights assigned to a cluster to CLUSTER_COUNT_MASK (which is 1 less than MAX_POINT_LIGHTS) to avoid overflowing into the offset bits

notes:

  • a better solution to the overflow may be to use more than 8 bits for cluster_count (the comment states only 14 of the remaining 24 bits are used for the offset). this would touch more of the code base but i'm happy to try if it has some benefit.
  • intensity is only one way to select lights. it may be worth allowing user configuration of the light filtering, but i can't see a clean way to do that

@github-actions github-actions bot added the S-Needs-Triage This issue needs to be labelled label Feb 11, 2022
@superdump superdump added A-Rendering Drawing game state to the screen and removed S-Needs-Triage This issue needs to be labelled labels Feb 11, 2022
@alice-i-cecile alice-i-cecile added the C-Bug An unexpected or incorrect behavior label Feb 11, 2022
@robtfm robtfm marked this pull request as draft February 11, 2022 22:59
@robtfm robtfm marked this pull request as ready for review February 14, 2022 11:27
@robtfm
Copy link
Contributor Author

robtfm commented Feb 14, 2022

after reviewing with @superdump,

  • removed the intensity step from the light filter - choosing lights that have most effect on the scene is a hard problem and using intensity is bad enough to be not worth doing
  • increased the CLUSTER_COUNT_SIZE so that the current max lights fit with some room to spare

this means that users should be filtering lights themselves based on their own preferred strategy. to be feasible this will mean adding a visiblity filter to point lights. this is not included here since there is ongoing discussion about bools vs marker components that we would like @cart to weigh in on.

Copy link
Contributor

@superdump superdump left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the one question, otherwise LGTM. When the question is answered, I'll mark it as ready for final review.

crates/bevy_pbr/src/light.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@superdump superdump left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of small changes then LGTM.

crates/bevy_pbr/src/light.rs Outdated Show resolved Hide resolved
crates/bevy_pbr/src/light.rs Outdated Show resolved Hide resolved
@superdump superdump added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Feb 25, 2022
.collect();

if lights.len() > MAX_POINT_LIGHTS {
warn!("MAX_POINT_LIGHTS ({}) exceeded", MAX_POINT_LIGHTS);
Copy link
Member

@mockersf mockersf Feb 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a fan of logs that will potentially happen on every frame

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree, but it should definitely be emitted once.

is it reasonable to add a Local to check if the warning has been emitted already?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that if there are other logs then it may get lost. I think we need a general pattern for this. Perhaps something like a Local<> that holds the last time we logged, and then just log once every 10s or something?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, I would keep it that way for now rather than add an additional parameter... there are a few other places with similar issues, we don't have the good solution for that yet

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally the logger should be able to detect duplicate logs and only log them once in a while 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For something that should be "fixed" i'm cool with warning every frame (until we can suppress more intelligently). But in this case, complex scenes could easily go over the max point light limit. This isn't "wrong" and I dont think we should be aggressively pushing people to hide lights that go over the limit.

Manually suppressing duplicate warnings is important to do here imo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cart what do you think of my suggestion above as an approach to 'rate limiting' the log?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

limited to warning once for now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@superdump yeah i like that, although I'm cool with logging once for now. "rate limiting" is an option, but we could also consider detecting fluctuations in light counts (ex: if you go under the limit and then back over, we print the warning again).

crates/bevy_pbr/src/light.rs Outdated Show resolved Hide resolved

// check each light against each view's frustum, keep only those that affect at least one of our views
let frusta: Vec<_> = views.iter().map(|(_, _, _, frustum, _)| *frustum).collect();
*lights = (*lights)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use retain here to avoid the extra allocation (combine the filter predicate with a captured counter to limit to MAX_POINT_LIGHTS + 1 and remove the remaining lights)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, thanks. the checks are failing now but i think it's not my fault?

Copy link
Member

@cart cart Mar 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup its a github linux-vm CI problem. Bleh :)

@cart
Copy link
Member

cart commented Mar 1, 2022

bors r+

bors bot pushed a commit that referenced this pull request Mar 1, 2022
# Objective

fix #3915 

## Solution

the issues are caused by
- lights are assigned to clusters before being filtered down to MAX_POINT_LIGHTS, leading to cluster counts potentially being too high
- after fixing the above, packing the count into 8 bits still causes overflow with exactly 256 lights affecting a cluster

to fix:

```assign_lights_to_clusters```
- limit extracted lights to MAX_POINT_LIGHTS, selecting based on shadow-caster & intensity (if required)
- warn if MAX_POINT_LIGHT count is exceeded

```prepare_lights```
- limit the lights assigned to a cluster to CLUSTER_COUNT_MASK (which is 1 less than MAX_POINT_LIGHTS) to avoid overflowing into the offset bits

notes:
- a better solution to the overflow may be to use more than 8 bits for cluster_count (the comment states only 14 of the remaining 24 bits are used for the offset). this would touch more of the code base but i'm happy to try if it has some benefit.
- intensity is only one way to select lights. it may be worth allowing user configuration of the light filtering, but i can't see a clean way to do that
@bors bors bot changed the title fix issues with too many point lights [Merged by Bors] - fix issues with too many point lights Mar 1, 2022
@bors bors bot closed this Mar 1, 2022
bors bot pushed a commit that referenced this pull request Mar 5, 2022
# Objective

Add Visibility for lights

## Solution

- add Visibility to PointLightBundle and DirectionLightBundle
- filter lights used by Visibility.is_visible

note: includes changes from #3916 due to overlap, will be cleaner after that is merged
kurtkuehnert pushed a commit to kurtkuehnert/bevy that referenced this pull request Mar 6, 2022
# Objective

fix bevyengine#3915 

## Solution

the issues are caused by
- lights are assigned to clusters before being filtered down to MAX_POINT_LIGHTS, leading to cluster counts potentially being too high
- after fixing the above, packing the count into 8 bits still causes overflow with exactly 256 lights affecting a cluster

to fix:

```assign_lights_to_clusters```
- limit extracted lights to MAX_POINT_LIGHTS, selecting based on shadow-caster & intensity (if required)
- warn if MAX_POINT_LIGHT count is exceeded

```prepare_lights```
- limit the lights assigned to a cluster to CLUSTER_COUNT_MASK (which is 1 less than MAX_POINT_LIGHTS) to avoid overflowing into the offset bits

notes:
- a better solution to the overflow may be to use more than 8 bits for cluster_count (the comment states only 14 of the remaining 24 bits are used for the offset). this would touch more of the code base but i'm happy to try if it has some benefit.
- intensity is only one way to select lights. it may be worth allowing user configuration of the light filtering, but i can't see a clean way to do that
kurtkuehnert pushed a commit to kurtkuehnert/bevy that referenced this pull request Mar 6, 2022
# Objective

Add Visibility for lights

## Solution

- add Visibility to PointLightBundle and DirectionLightBundle
- filter lights used by Visibility.is_visible

note: includes changes from bevyengine#3916 due to overlap, will be cleaner after that is merged
aevyrie pushed a commit to aevyrie/bevy that referenced this pull request Jun 7, 2022
# Objective

Add Visibility for lights

## Solution

- add Visibility to PointLightBundle and DirectionLightBundle
- filter lights used by Visibility.is_visible

note: includes changes from bevyengine#3916 due to overlap, will be cleaner after that is merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

too many point lights behave strangely
5 participants