-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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] - Always update clusters and remove per-frame allocations #4169
Conversation
I'm curious about the perf impact; do we have a good benchmark for this? |
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.
sorry for the regression. doing serial PRs on this area feels a bit like trying to replace the wheels on a car while driving it... but i hope i'll learn and improve as we go.
is it possible to get examples to run as part of CI?
Part of them already run using swiftshader. |
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 full review.
I benchmarked |
I think this is good to go now. Feel free to leave more feedback, but I'll merge this in the next few days if i dont hear back from anyone. |
looks good. in testing i found an unrelated issue, if you want to include it that would be great, otherwise i'll open another pr. the obb test is occasionally failing in Single mode due to f32 precision issues. we can fix it by removing the 1e9s and calculating the actual depth we need: @@ -323,7 +323,7 @@ impl ClusterConfig {
fn first_slice_depth(&self) -> f32 {
match self {
ClusterConfig::None => 0.0,
- ClusterConfig::Single => 1.0e9, // FIXME note can't use f32::MAX as the aabb explodes
+ ClusterConfig::Single => 0.0,
ClusterConfig::XYZ { z_config, .. } | ClusterConfig::FixedZ { z_config, .. } => {
z_config.first_slice_depth
}
@@ -333,7 +333,7 @@ impl ClusterConfig {
fn far_z_mode(&self) -> ClusterFarZMode {
match self {
ClusterConfig::None => ClusterFarZMode::Constant(0.0),
- ClusterConfig::Single => ClusterFarZMode::Constant(1.0e9), // FIXME note can't use f32::MAX as the aabb explodes
+ ClusterConfig::Single => ClusterFarZMode::MaxLightRange,
ClusterConfig::XYZ { z_config, .. } | ClusterConfig::FixedZ { z_config, .. } => {
z_config.far_z_mode
} |
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.
LGTM. It would be good to add in robtfm's noted fix too.
@cart ping? I want to get this in as I have a couple more PRs that will come on top of this. I’ll add some many lights example while I’m at it I guess so we have something to test with. I’ve used Sponza locally but it’s not really necessary. :) |
Ill update this now and get it merged! |
bors r+ |
* Refactor assign_lights_to_clusters to always clear + update clusters, even if the screen size isn't available yet / is zero. This fixes #4167. We still avoid the "expensive" per-light work when the screen size isn't available yet. I also consolidated some logic to eliminate some redundancies. * Removed _a ton_ of (potentially very large) per-frame reallocations * Removed `Res<VisiblePointLights>` (a vec) in favor of `Res<GlobalVisiblePointLights>` (a hashmap). We were allocating a new hashmap every frame, the collecting it into a vec every frame, then in another system _re-generating the hashmap_. It is always used like a hashmap, might as well embrace that. We now reuse the same hashmap every frame and dont use any intermediate collections. * We were re-allocating Clusters aabb and light vectors every frame by re-constructing Clusters every frame. We now re-use the existing collections. * Reuse per-camera VisiblePointLight vecs when possible instead of allocating them every frame. We now only insert VisiblePointLights if the component doesn't exist yet.
) * Refactor assign_lights_to_clusters to always clear + update clusters, even if the screen size isn't available yet / is zero. This fixes bevyengine#4167. We still avoid the "expensive" per-light work when the screen size isn't available yet. I also consolidated some logic to eliminate some redundancies. * Removed _a ton_ of (potentially very large) per-frame reallocations * Removed `Res<VisiblePointLights>` (a vec) in favor of `Res<GlobalVisiblePointLights>` (a hashmap). We were allocating a new hashmap every frame, the collecting it into a vec every frame, then in another system _re-generating the hashmap_. It is always used like a hashmap, might as well embrace that. We now reuse the same hashmap every frame and dont use any intermediate collections. * We were re-allocating Clusters aabb and light vectors every frame by re-constructing Clusters every frame. We now re-use the existing collections. * Reuse per-camera VisiblePointLight vecs when possible instead of allocating them every frame. We now only insert VisiblePointLights if the component doesn't exist yet.
) * Refactor assign_lights_to_clusters to always clear + update clusters, even if the screen size isn't available yet / is zero. This fixes bevyengine#4167. We still avoid the "expensive" per-light work when the screen size isn't available yet. I also consolidated some logic to eliminate some redundancies. * Removed _a ton_ of (potentially very large) per-frame reallocations * Removed `Res<VisiblePointLights>` (a vec) in favor of `Res<GlobalVisiblePointLights>` (a hashmap). We were allocating a new hashmap every frame, the collecting it into a vec every frame, then in another system _re-generating the hashmap_. It is always used like a hashmap, might as well embrace that. We now reuse the same hashmap every frame and dont use any intermediate collections. * We were re-allocating Clusters aabb and light vectors every frame by re-constructing Clusters every frame. We now re-use the existing collections. * Reuse per-camera VisiblePointLight vecs when possible instead of allocating them every frame. We now only insert VisiblePointLights if the component doesn't exist yet.
Res<VisiblePointLights>
(a vec) in favor ofRes<GlobalVisiblePointLights>
(a hashmap). We were allocating a new hashmap every frame, the collecting it into a vec every frame, then in another system re-generating the hashmap. It is always used like a hashmap, might as well embrace that. We now reuse the same hashmap every frame and dont use any intermediate collections.