Skip to content
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

Make render phases render world resources instead of components. #13277

Merged
merged 8 commits into from May 21, 2024

Conversation

pcwalton
Copy link
Contributor

@pcwalton pcwalton commented May 7, 2024

This commit makes us stop using the render world ECS for BinnedRenderPhase and SortedRenderPhase and instead use resources with EntityHashMaps inside. There are three reasons to do this:

  1. We can use clear() to clear out the render phase collections instead of recreating the components from scratch, allowing us to reuse allocations.

  2. This is a prerequisite for retained bins, because components can't be retained from frame to frame in the render world, but resources can.

  3. We want to move away from storing anything in components in the render world ECS, and this is a step in that direction.

This patch results in a small performance benefit, due to point (1) above.

Changelog

Changed

  • The BinnedRenderPhase and SortedRenderPhase render world components have been replaced with ViewBinnedRenderPhases and ViewSortedRenderPhases resources.

Migration Guide

  • The BinnedRenderPhase and SortedRenderPhase render world components have been replaced with ViewBinnedRenderPhases and ViewSortedRenderPhases resources. Instead of querying for the components, look the camera entity up in the ViewBinnedRenderPhases/ViewSortedRenderPhases tables.

This commit makes us stop using the render world ECS for
`BinnedRenderPhase` and `SortedRenderPhase` and instead use resources
with `EntityHashMap`s inside. There are three reasons to do this:

1. We can use `clear()` to clear out the render phase collections
   instead of recreating the components from scratch, allowing us to
   reuse allocations.

2. This is a prerequisite for retained bins, because components can't be
   retained from frame to frame in the render world, but resources can.

3. We want to move away from storing anything in components in the
   render world ECS, and this is a step in that direction.

This patch results in a small performance benefit, due to point (1)
above.
@pcwalton pcwalton added A-Rendering Drawing game state to the screen C-Performance A change motivated by improving speed, memory usage or compile times C-Code-Quality A section of code that is hard to understand or change C-Breaking-Change A breaking change to Bevy's public API that needs to be noted in a migration guide labels May 7, 2024
Copy link
Contributor

@ChristopherBiscardi ChristopherBiscardi left a comment

Choose a reason for hiding this comment

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

seems relatively straightforward as far as changes go. code flow changes (like !camera.active { continue }) make sense to me. I was able to run the 3d_shapes example using this PR and add a system that accessed and logged out the resources, seeing the relevant camera entity.

consider my review partial since I haven't done many rendering reviews yet.

Copy link
Contributor

@robtfm robtfm left a comment

Choose a reason for hiding this comment

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

looks good.

i guess iterating all views and filtering for those with matching phases could be slower than using query filters (as we were before), but views are very low count so i don't think it'll ever be significant.

crates/bevy_core_pipeline/src/core_2d/mod.rs Show resolved Hide resolved
crates/bevy_core_pipeline/src/core_3d/mod.rs Show resolved Hide resolved
crates/bevy_ui/src/render/mod.rs Show resolved Hide resolved
Copy link
Contributor

@NthTensor NthTensor left a comment

Choose a reason for hiding this comment

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

Haven't looked at the code yet. I profiled on the following scenes:

  • San Miguel
  • Bistro

I found no significant performance degradation or improvement on my (extremely GPU bound) laptop (11th gen i7 w/ integrated graphics).

I tested the following examples and found no visual artifacts or other issues compared to current main:

  • 2d_shape
  • atomospheric_fog
  • color_animation
  • pbr
  • many_foxes
  • gltf_skinned_mesh
  • motion_blur

Approving based on tests. Will take a look at the code when I can.

@pcwalton
Copy link
Contributor Author

Addressed review comments.

@pcwalton pcwalton requested a review from robtfm May 16, 2024 23:27
Copy link
Contributor

@robtfm robtfm left a comment

Choose a reason for hiding this comment

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

nit: all those EntityHashSets could be Locals to avoid allocs each frame

@pcwalton
Copy link
Contributor Author

Marking as draft not only because of the review comment but also because this triggered #13402, which it should not have, so I want to figure out why that is.

@pcwalton pcwalton marked this pull request as draft May 17, 2024 00:13
@pcwalton pcwalton marked this pull request as draft May 17, 2024 00:13
This fixes the problem that led to bevyengine#13402.

I'm not sure if this had any negative consequences, but it didn't
replicate the prior behavior with the `Or` query filter, so I changed it
to match.
@pcwalton
Copy link
Contributor Author

I found the problem. queue_prepass_material_meshes() wasn't skipping views that had no place to put the meshes. As a result, some meshes got added to queues that weren't before, causing #13402.

I don't think they were actually rendered, but this was inefficient, so I added the check back.

@pcwalton pcwalton marked this pull request as ready for review May 17, 2024 04:44
@pcwalton pcwalton requested a review from robtfm May 17, 2024 04:45
@pcwalton pcwalton added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label May 18, 2024
github-merge-queue bot pushed a commit that referenced this pull request May 18, 2024
Commit 3f5a090 added a reference to
`STANDARD_MATERIAL_FLAGS_BASE_COLOR_UV_BIT`, a nonexistent identifier,
in the alpha discard portion of the prepass shader. Moreover, the logic
didn't make sense to me. I think the code was trying to choose between
the two UV sets depending on which is present, so I made it do that.

I noticed this when trying Bistro with #13277. I'm not sure why this
issue didn't manifest itself before, but it's clearly a bug, so here's a
fix. We should probably merge this before 0.14.
@pcwalton pcwalton added this to the 0.15 milestone May 20, 2024
Copy link
Contributor

@ricky26 ricky26 left a comment

Choose a reason for hiding this comment

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

Seems pretty straight-forward. Some of the check-and-bail-outs added irk me a little because they might wind up as silent failures, but it's not a regression compared to the query filter before.

let view_entity = graph.view_entity();
let Some(transparent_phase) = transparent_phases.get(&view_entity) else {
return Ok(());
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Since this is now a resource and inserted during extract, is this case even possible? It strikes me that even if it can happen, that it would be surprising/erroneous. Might merit a warning and/or .expect?

(It looks like most of the new resource accesses follow this pattern.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From what I can tell, Bevy style is to use bailouts like this even when the problem should never happen to reduce unwinding overhead. This may or may not be a good thing, but I try to follow it. We could use error! there though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, this will happen normally for the view entities that are created for cascaded shadow maps. Since shadow maps don't render any transparent meshes, their view entities won't have entries in ViewSortedRenderPhases<Transparent3d>. This is fine and skipping them is the correct thing to do. So this logic is correct as is, I believe.

@alice-i-cecile alice-i-cecile added this pull request to the merge queue May 21, 2024
Merged via the queue into bevyengine:main with commit 9da0b2a May 21, 2024
28 checks passed
pcwalton added a commit to pcwalton/bevy that referenced this pull request May 21, 2024
We invoked the `extract_default_ui_camera_view` system twice: once for
2D cameras and once for 3D cameras. This was fine before moving to
resources for render phases, but, after the move to resources, the first
thing such systems do is to clear out all the entities-to-be-rendered
from the previous frame. So, if the scheduler happened to run
`extract_default_ui_camera_view::<Camera2d>` first, then all the UI
elements that it queued would be overwritten by the
`extract_default_ui_camera_view::<Camera3d>` system, or vice versa. The
ordering dependence is the reason why this problem was intermittent.

This commit fixes the problem by merging the two systems into one
systems, using an `Or` query filter.
github-merge-queue bot pushed a commit that referenced this pull request May 21, 2024
We invoked the `extract_default_ui_camera_view` system twice: once for
2D cameras and once for 3D cameras. This was fine before moving to
resources for render phases, but, after the move to resources, the first
thing such systems do is to clear out all the entities-to-be-rendered
from the previous frame. So, if the scheduler happened to run
`extract_default_ui_camera_view::<Camera2d>` first, then all the UI
elements that it queued would be overwritten by the
`extract_default_ui_camera_view::<Camera3d>` system, or vice versa. The
ordering dependence is the reason why this problem was intermittent.

This commit fixes the problem by merging the two systems into one
systems, using an `Or` query filter.

## Migration Guide

* The `bevy_ui::render::extract_default_ui_camera_view` system is no
longer parameterized over the specific type of camera and is hard-wired
to either `Camera2d` or `Camera3d` components.
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-Breaking-Change A breaking change to Bevy's public API that needs to be noted in a migration guide C-Code-Quality A section of code that is hard to understand or change C-Performance A change motivated by improving speed, memory usage or compile times S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants