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

Turn on GPU culling automatically if the target platform supports it. #16670

Closed
wants to merge 10 commits into from

Conversation

pcwalton
Copy link
Contributor

@pcwalton pcwalton commented Dec 6, 2024

This commit removes the undocumented GpuCulling component in favor of automatically turning GPU culling on when the platform supports it. The main reason to make GPU culling automatic is that GPU culling enables indirect mode. Indirect mode is needed for multidraw (#16427), because non-indirect multidraw doesn't exist in wgpu. Since multidraw is such a win for performance, when that feature is supported the small performance tax that indirect mode incurs is virtually always worth paying.

CPU culling is always used in addition to GPU culling unless the NoCpuCulling component is placed on the camera. This results in some amount of redundant computation on the GPU, but the overhead is negligible. I figured that the GPU time savings gained from skipping this computation when not needed didn't outweigh the costs of the added complexity that would be necessarily to implement that optimization, especially with GPU two-phase occlusion culling on the horizon.

Migration Guide

  • The GpuCulling component has been removed. GPU culling is now automatically enabled for all cameras if the hardware and platform support it.

This commit removes the undocumented `GpuCulling` component in favor of
automatically turning GPU culling on when the platform supports it. The
main reason to make GPU culling automatic is that GPU culling enables
indirect mode. Indirect mode is needed for multidraw (bevyengine#16427), because
non-indirect multidraw doesn't exist in `wgpu`. Since multidraw is such
a win for performance, when that feature is supported the small
performance tax that indirect mode incurs is virtually always worth
paying.

CPU culling is always used in addition to GPU culling unless the
`NoCpuCulling` component is placed on the camera. This results in some
amount of redundant computation on the GPU, but the overhead is
negligible. I figured that the GPU time savings gained from skipping
this computation when not needed didn't outweigh the costs of the added
complexity that would be necessarily to implement that optimization,
especially with GPU two-phase occlusion culling on the horizon.
@pcwalton pcwalton added A-Rendering Drawing game state to the screen C-Performance A change motivated by improving speed, memory usage or compile times S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Dec 6, 2024
@alice-i-cecile alice-i-cecile added the M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide label Dec 6, 2024
Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

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

Good, I think this is a better design.

@pcwalton pcwalton requested a review from IceSentry December 6, 2024 06:48
pcwalton added a commit to pcwalton/bevy that referenced this pull request Dec 6, 2024
This patch makes shadows use multidraw when the camera they'll be drawn
to has the `GpuCulling` component. This results in a significant
reduction in drawcalls; Bistro Exterior drops to 3 drawcalls for each
shadow cascade.

Note that PR bevyengine#16670 will remove the `GpuCulling` component, making
shadows automatically use multidraw. Beware of that when testing this
patch; before bevyengine#16670 lands, you'll need to manually add `GpuCulling` to
your camera in order to see any performance benefits.
Copy link
Contributor

@JMS55 JMS55 left a comment

Choose a reason for hiding this comment

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

Approved once docs are fixed (see CI).

@pcwalton pcwalton 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 Dec 6, 2024
Copy link
Contributor

@bushrat011899 bushrat011899 left a comment

Choose a reason for hiding this comment

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

Tested many_cubes in Windows 10 on a i5 1240P Framework 13 and everything appears to be working as expected. Code definitely looks cleaner too!

@alice-i-cecile
Copy link
Member

Testing via example run.

@pcwalton
Copy link
Contributor Author

I believe the failure is #15981.

@rparrett
Copy link
Contributor

These seem to be the finished runs:

mac:
https://pixel-eagle.com/project/b25a040a-a980-4602-b90c-d480ab84076d/run/5862/compare/5815
linux:
https://pixel-eagle.com/project/b25a040a-a980-4602-b90c-d480ab84076d/run/5863/compare/5816

Looks like ssr, custom_shader_instancing, deferred_rendering are probably real issues, and the rest are known flakiness.

@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it labels Dec 10, 2024
github-merge-queue bot pushed a commit that referenced this pull request Dec 10, 2024
This patch makes shadows use multidraw when the camera they'll be drawn
to has the `GpuCulling` component. This results in a significant
reduction in drawcalls; Bistro Exterior drops to 3 drawcalls for each
shadow cascade.

Note that PR #16670 will remove the `GpuCulling` component, making
shadows automatically use multidraw. Beware of that when testing this
patch; before #16670 lands, you'll need to manually add `GpuCulling` to
your camera in order to see any performance benefits.
BD103 pushed a commit to BD103/bevy that referenced this pull request Dec 10, 2024
This patch makes shadows use multidraw when the camera they'll be drawn
to has the `GpuCulling` component. This results in a significant
reduction in drawcalls; Bistro Exterior drops to 3 drawcalls for each
shadow cascade.

Note that PR bevyengine#16670 will remove the `GpuCulling` component, making
shadows automatically use multidraw. Beware of that when testing this
patch; before bevyengine#16670 lands, you'll need to manually add `GpuCulling` to
your camera in order to see any performance benefits.
pcwalton added a commit to pcwalton/bevy that referenced this pull request Dec 10, 2024
multidraw.

This commit resolves most of the failures seen in bevyengine#16670. It contains
two major fixes:

1. The prepass shaders weren't updated for bindless mode, so they were
   accessing `material` as a single element instead of as an array. I
   added the needed `BINDLESS` check.

2. If the mesh didn't support batch set keys (i.e. `get_batch_set_key()`
   returns `None`), and multidraw was enabled, the batching logic would
   try to multidraw all the meshes in a bin together instead of
   disabling multidraw. This is because we checked whether the
   `Option<BatchSetKey>` for the previous batch was equal to the
   `Option<BatchSetKey>` for the next batch to determine whether objects
   could be multidrawn together, which would return true if batch set
   keys were absent, causing an entire bin to be multidrawn together.
   This patch fixes the logic so that multidraw is only enabled if the
   batch set keys match *and are `Some`*.

Additionally, this commit adds batch key support for bins that use
`Opaque3dNoLightmapBinKey`, which in practice means prepasses.
Consequently, this patch enables multidraw for the prepass when GPU
culling is enabled.

When testing this patch, try adding `GpuCulling` to the camera in the
`deferred_rendering` and `ssr` examples. You can see that these examples
break without this patch and work properly with it.
pcwalton added a commit to pcwalton/bevy that referenced this pull request Dec 10, 2024
default.

This patch replaces the undocumented `NoGpuCulling` component with a new
component, `NoIndirectDrawing`, effectively turning indirect drawing on
by default. Indirect mode is needed for the recently-landed multidraw
feature (bevyengine#16427). Since multidraw is such a win for performance, when
that feature is supported the small performance tax that indirect mode
incurs is virtually always worth paying.

To ensure that custom drawing code such as that in the
`custom_shader_instancing` example continues to function, this commit
additionally makes GPU culling take the `NoFrustumCulling` component
into account.

This PR is an alternative to bevyengine#16670 that doesn't break the
`custom_shader_instancing` example. **PR bevyengine#16755 should land first in
order to avoid breaking deferred rendering, as multidraw currently
breaks it**.
@pcwalton
Copy link
Contributor Author

Closed in favor of #16755 and #16757.

@pcwalton pcwalton closed this Dec 10, 2024
github-merge-queue bot pushed a commit that referenced this pull request Dec 12, 2024
…d multidraw. (#16755)

This commit resolves most of the failures seen in #16670. It contains
two major fixes:

1. The prepass shaders weren't updated for bindless mode, so they were
accessing `material` as a single element instead of as an array. I added
the needed `BINDLESS` check.

2. If the mesh didn't support batch set keys (i.e. `get_batch_set_key()`
returns `None`), and multidraw was enabled, the batching logic would try
to multidraw all the meshes in a bin together instead of disabling
multidraw. This is because we checked whether the `Option<BatchSetKey>`
for the previous batch was equal to the `Option<BatchSetKey>` for the
next batch to determine whether objects could be multidrawn together,
which would return true if batch set keys were absent, causing an entire
bin to be multidrawn together. This patch fixes the logic so that
multidraw is only enabled if the batch set keys match *and are `Some`*.

Additionally, this commit adds batch key support for bins that use
`Opaque3dNoLightmapBinKey`, which in practice means prepasses.
Consequently, this patch enables multidraw for the prepass when GPU
culling is enabled.

When testing this patch, try adding `GpuCulling` to the camera in the
`deferred_rendering` and `ssr` examples. You can see that these examples
break without this patch and work properly with it.

---------

Co-authored-by: Alice Cecile <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Dec 13, 2024
…y default. (#16757)

This patch replaces the undocumented `NoGpuCulling` component with a new
component, `NoIndirectDrawing`, effectively turning indirect drawing on
by default. Indirect mode is needed for the recently-landed multidraw
feature (#16427). Since multidraw is such a win for performance, when
that feature is supported the small performance tax that indirect mode
incurs is virtually always worth paying.

To ensure that custom drawing code such as that in the
`custom_shader_instancing` example continues to function, this commit
additionally makes GPU culling take the `NoFrustumCulling` component
into account.

This PR is an alternative to #16670 that doesn't break the
`custom_shader_instancing` example. **PR #16755 should land first in
order to avoid breaking deferred rendering, as multidraw currently
breaks it**.

## Migration Guide

* Indirect drawing (GPU culling) is now enabled by default, so the
`GpuCulling` component is no longer available. To disable indirect mode,
which may be useful with custom render nodes, add the new
`NoIndirectDrawing` component to your camera.
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-Performance A change motivated by improving speed, memory usage or compile times M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

6 participants