Don't mark newly-hidden meshes invisible until all visibility-determining systems run.#17922
Merged
superdump merged 4 commits intobevyengine:mainfrom Feb 18, 2025
Merged
Conversation
visibility-determining systems run. The `check_visibility` system currently follows this algorithm: 1. Store all meshes that were visible last frame in the `PreviousVisibleMeshes` set. 2. Determine which meshes are visible. For each such visible mesh, remove it from `PreviousVisibleMeshes`. 3. Mark all meshes that remain in `PreviousVisibleMeshes` as invisible. This algorithm would be correct if the `check_visibility` were the only system that marked meshes visible. However, it's not: the shadow-related systems `check_dir_light_mesh_visibility` and `check_point_light_mesh_visibility` can as well. This results in the following sequence of events for meshes that are in a shadow map but *not* visible from a camera: A. `check_visibility` runs, finds that no camera contains these meshes, and marks them hidden, which sets the changed flag. B. `check_dir_light_mesh_visibility` and/or `check_point_light_mesh_visibility` run, discover that these meshes are visible in the shadow map, and marks them as visible, again setting the `ViewVisibility` changed flag. C. During the extraction phase, the mesh extraction system sees that `ViewVisibility` is changed and re-extracts the mesh. This is inefficient and results in needless work during rendering. This patch fixes the issue in two ways: * The `check_dir_light_mesh_visibility` and `check_point_light_mesh_visibility` systems now remove meshes that they discover from `PreviousVisibleMeshes`. * Step (3) above has been moved from `check_visibility` to a separate system, `mark_newly_hidden_entities_invisible`. This system runs after all visibility-determining systems, ensuring that `PreviousVisibleMeshes` contains only those meshes that truly became invisible on this frame. This fix dramatically improves the performance of [the Caldera benchmark], when combined with several other patches I've submitted.
superdump
approved these changes
Feb 18, 2025
tychedelia
approved these changes
Feb 18, 2025
Member
tychedelia
left a comment
There was a problem hiding this comment.
Awesome, this makes a lot more sense.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
check_visibilitysystem currently follows this algorithm:Store all meshes that were visible last frame in the
PreviousVisibleMeshesset.Determine which meshes are visible. For each such visible mesh, remove it from
PreviousVisibleMeshes.Mark all meshes that remain in
PreviousVisibleMeshesas invisible.This algorithm would be correct if the
check_visibilitywere the only system that marked meshes visible. However, it's not: the shadow-related systemscheck_dir_light_mesh_visibilityandcheck_point_light_mesh_visibilitycan as well. This results in the following sequence of events for meshes that are in a shadow map but not visible from a camera:A.
check_visibilityruns, finds that no camera contains these meshes,and marks them hidden, which sets the changed flag.
B.
check_dir_light_mesh_visibilityand/orcheck_point_light_mesh_visibilityrun, discover that these meshesare visible in the shadow map, and marks them as visible, again
setting the
ViewVisibilitychanged flag.C. During the extraction phase, the mesh extraction system sees that
ViewVisibilityis changed and re-extracts the mesh.This is inefficient and results in needless work during rendering.
This patch fixes the issue in two ways:
The
check_dir_light_mesh_visibilityandcheck_point_light_mesh_visibilitysystems now remove meshes that they discover fromPreviousVisibleMeshes.Step (3) above has been moved from
check_visibilityto a separate system,mark_newly_hidden_entities_invisible. This system runs after all visibility-determining systems, ensuring thatPreviousVisibleMeshescontains only those meshes that truly became invisible on this frame.This fix dramatically improves the performance of the Caldera benchmark, when combined with several other patches I've submitted.