-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Conversation
after reviewing with @superdump,
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. |
There was a problem hiding this 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.
There was a problem hiding this 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.
.collect(); | ||
|
||
if lights.len() > MAX_POINT_LIGHTS { | ||
warn!("MAX_POINT_LIGHTS ({}) exceeded", MAX_POINT_LIGHTS); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 🤔
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
|
||
// 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) |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 :)
bors r+ |
# 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
# 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
# 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
# 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
# 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
Objective
fix #3915
Solution
the issues are caused by
to fix:
assign_lights_to_clusters
prepare_lights
notes: