Skip to content

Fix the behavior of NoCpuCulling when toggled at runtime.#23534

Merged
alice-i-cecile merged 1 commit intobevyengine:mainfrom
pcwalton:no-cpu-culling-changes
Mar 28, 2026
Merged

Fix the behavior of NoCpuCulling when toggled at runtime.#23534
alice-i-cecile merged 1 commit intobevyengine:mainfrom
pcwalton:no-cpu-culling-changes

Conversation

@pcwalton
Copy link
Copy Markdown
Contributor

@pcwalton pcwalton commented Mar 27, 2026

Currently, adding NoCpuCulling to a mesh on a frame after that mesh was spawned causes that mesh to disappear. This is due to two bugs:

  1. Meshes are unconditionally, and incorrectly, added to RenderGpuCulledEntities, even if they are subject to CPU culling. Entities are only added to the GPU culling bucket if they (1) don't participate in CPU culling, (2) are in RenderGpuCulledEntities now, and (3) weren't in RenderGpuCulledEntities before. Right now, since entities are always in RenderGpuCullingEntities, these conditions are never met when adding NoCpuCulling to an existing mesh that didn't have that component before. This PR fixes the issue by excluding entities without the NoCpuCulling component from RenderGpuCulledEntities.

  2. The extract_meshes_for_gpu_building system tries to extract meshes for which Changed<NoCpuCulling> is true, but it fails because the query is written like Or<(Changed<Foo>, (Changed<Bar>, Changed<NoCpuCulling>))> instead of Or<(Changed<Foo>, Or<(Changed<Bar>, Changed<NoCpuCulling>)>)>. The former is interpreted as Changed(Foo) || (Changed(Bar) && Changed(NoCpuCulling)) instead of Changed(Foo) || Changed(Bar) || Changed(NoCpuCulling), which was the intention. Because of this, we were failing to extract meshes that had NoCpuCulling assigned to them unless they were changed in some other way.

This PR fixes both of these issues, and also refactors extract_meshes_for_gpu_building a bit to reduce rightward drift.

This issue was noticed when attempting to add a check box to bevy_city to disable CPU culling. I went ahead and added the check box to that example, now that the issue preventing it from working is fixed.

Currently, adding `NoCpuCulling` to a mesh causes that mesh to
disappear. This is due to two bugs:

1. Meshes are unconditionally, and incorrectly, added to
   `RenderGpuCulledEntities`, even if they are subject to CPU culling.
   Entities are only added to the GPU culling bucket if they (1) don't
   participate in CPU culling, (2) are in `RenderGpuCulledEntities`
   *now*, and (3) weren't in `RenderGpuCulledEntities` *before*. Right
   now, since entities are always in `RenderGpuCullingEntities`, these
   conditions are never met. This PR fixes the issue by excluding
   entities without the `NoCpuCulling` component from
   `RenderGpuCulledEntities`.

2. The `extract_meshes_for_gpu_building` system tries to extract meshes
   for which `Changed<NoCpuCulling>` is true, but it fails because the
   query is written like `Or<(Changed<Foo>, (Changed<Bar>,
   Changed<NoCpuCulling>))>` instead of `Or<(Changed<Foo>,
   Or<(Changed<Bar>, Changed<NoCpuCulling>)>)>`. The former is
   interpreted as `Changed(Foo) || (Changed(Bar) &&
   Changed(NoCpuCulling))` instead of `Changed(Foo) || Changed(Bar) ||
   Changed(NoCpuCulling)`, which was the intention. Because of this, we
   were failing to extract meshes that had `NoCpuCulling` assigned to
   them unless they were changed in some other way.

This issue was noticed when attempting to add a check box to `bevy_city`
to disable CPU culling. I went ahead and added the check box to that
example, now that the issue preventing it from working is fixed.
@pcwalton pcwalton added the A-Rendering Drawing game state to the screen label Mar 27, 2026
@github-project-automation github-project-automation bot moved this to Needs SME Triage in Rendering Mar 27, 2026
@pcwalton pcwalton added S-Needs-Review Needs reviewer attention (from anyone!) to move forward C-Bug An unexpected or incorrect behavior labels Mar 27, 2026
Copy link
Copy Markdown
Contributor

@IceSentry IceSentry left a comment

Choose a reason for hiding this comment

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

I can confirm it fixed the runtime change in bevy_city. Thanks for adding the checkbox!

Code looks good too.

@pcwalton
Copy link
Copy Markdown
Contributor Author

I think this obsoletes #23508

@IceSentry
Copy link
Copy Markdown
Contributor

Yeah, I'm pretty sure it does. At least this PR fixed everything for me so #23508 doesn't seem necessary

@alice-i-cecile alice-i-cecile added this to the 0.19 milestone Mar 27, 2026
@atlv24 atlv24 added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 27, 2026
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Mar 28, 2026
Merged via the queue into bevyengine:main with commit 96e4074 Mar 28, 2026
47 checks passed
@github-project-automation github-project-automation bot moved this from Needs SME Triage to Done in Rendering Mar 28, 2026
splo pushed a commit to splo/bevy that referenced this pull request Mar 31, 2026
…ne#23534)

Currently, adding `NoCpuCulling` to a mesh on a frame after that mesh
was spawned causes that mesh to disappear. This is due to two bugs:

1. Meshes are unconditionally, and incorrectly, added to
`RenderGpuCulledEntities`, even if they are subject to CPU culling.
Entities are only added to the GPU culling bucket if they (1) don't
participate in CPU culling, (2) are in `RenderGpuCulledEntities` *now*,
and (3) weren't in `RenderGpuCulledEntities` *before*. Right now, since
entities are always in `RenderGpuCullingEntities`, these conditions are
never met when adding `NoCpuCulling` to an existing mesh that didn't
have that component before. This PR fixes the issue by excluding
entities without the `NoCpuCulling` component from
`RenderGpuCulledEntities`.

2. The `extract_meshes_for_gpu_building` system tries to extract meshes
for which `Changed<NoCpuCulling>` is true, but it fails because the
query is written like `Or<(Changed<Foo>, (Changed<Bar>,
Changed<NoCpuCulling>))>` instead of `Or<(Changed<Foo>,
Or<(Changed<Bar>, Changed<NoCpuCulling>)>)>`. The former is interpreted
as `Changed(Foo) || (Changed(Bar) && Changed(NoCpuCulling))` instead of
`Changed(Foo) || Changed(Bar) || Changed(NoCpuCulling)`, which was the
intention. Because of this, we were failing to extract meshes that had
`NoCpuCulling` assigned to them unless they were changed in some other
way.

This PR fixes both of these issues, and also refactors
`extract_meshes_for_gpu_building` a bit to reduce rightward drift.

This issue was noticed when attempting to add a check box to `bevy_city`
to disable CPU culling. I went ahead and added the check box to that
example, now that the issue preventing it from working is fixed.
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.

4 participants