[Merged by Bors] - fix issues with too many point lights#3916
[Merged by Bors] - fix issues with too many point lights#3916robtfm wants to merge 16 commits intobevyengine:mainfrom
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. |
superdump
left a comment
There was a problem hiding this comment.
Just the one question, otherwise LGTM. When the question is answered, I'll mark it as ready for final review.
superdump
left a comment
There was a problem hiding this comment.
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.
not a fan of logs that will potentially happen on every frame
There was a problem hiding this comment.
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.
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.
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.
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.
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.
@cart what do you think of my suggestion above as an approach to 'rate limiting' the log?
There was a problem hiding this comment.
limited to warning once for now
There was a problem hiding this comment.
@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.
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.
good idea, thanks. the checks are failing now but i think it's not my fault?
There was a problem hiding this comment.
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_clustersprepare_lightsnotes: