Use multidraw for opaque meshes when GPU culling is in use.#16427
Merged
alice-i-cecile merged 10 commits intobevyengine:mainfrom Dec 6, 2024
Merged
Use multidraw for opaque meshes when GPU culling is in use.#16427alice-i-cecile merged 10 commits intobevyengine:mainfrom
alice-i-cecile merged 10 commits intobevyengine:mainfrom
Conversation
This commit adds support for *multidraw*, which is a feature that allows multiple meshes to be drawn in a single drawcall. `wgpu` currently implements multidraw on Vulkan, so this feature is only enabled there. Multiple meshes can be drawn at once if they're in the same vertex and index buffers and are otherwise placed in the same bin. (Thus, for example, at present the materials and textures must be identical, but see bevyengine#16368.) Multidraw is a significant performance improvement during the draw phase because it reduces the number of rebindings, as well as the amount of driver overhead. This feature is currently only enabled when GPU culling is used: i.e. when `GpuCulling` is present on a camera. Therefore, if you run for example `scene_viewer`, you will not see any performance improvements, because `scene_viewer` doesn't add the `GpuCulling` component to its camera. Additionally, the multidraw feature is only implemented for opaque 3D meshes and not for shadows or 2D meshes. I plan to make GPU culling the default and to extend the feature to shadows in the future. Also, in the future I suspect that polyfilling multidraw on APIs that don't support it will be fruitful, as even without driver-level support use of multidraw allows us to avoid expensive `wgpu` rebindings.
Contributor
Author
|
I'm marking this PR as a draft until 0.15 is out, to indicate that we shouldn't merge it before then. It should generally be ready to go, though; feel free to review. |
JMS55
approved these changes
Dec 1, 2024
Contributor
JMS55
left a comment
There was a problem hiding this comment.
Can't really test performance because I lack a desktop atm, but code lgtm.
IceSentry
approved these changes
Dec 2, 2024
Contributor
IceSentry
left a comment
There was a problem hiding this comment.
I haven't tested the code locally yet, but everything LGTM
Contributor
Author
|
Merge conflicts addressed. |
Member
|
Merge conflicts on this one :) |
Contributor
Author
|
Conflicts addressed. |
pcwalton
added a commit
to pcwalton/bevy
that referenced
this pull request
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 (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
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**.
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.
ecoskey
pushed a commit
to ecoskey/bevy
that referenced
this pull request
Jan 6, 2025
…ne#16427) This commit adds support for *multidraw*, which is a feature that allows multiple meshes to be drawn in a single drawcall. `wgpu` currently implements multidraw on Vulkan, so this feature is only enabled there. Multiple meshes can be drawn at once if they're in the same vertex and index buffers and are otherwise placed in the same bin. (Thus, for example, at present the materials and textures must be identical, but see bevyengine#16368.) Multidraw is a significant performance improvement during the draw phase because it reduces the number of rebindings, as well as the number of drawcalls. This feature is currently only enabled when GPU culling is used: i.e. when `GpuCulling` is present on a camera. Therefore, if you run for example `scene_viewer`, you will not see any performance improvements, because `scene_viewer` doesn't add the `GpuCulling` component to its camera. Additionally, the multidraw feature is only implemented for opaque 3D meshes and not for shadows or 2D meshes. I plan to make GPU culling the default and to extend the feature to shadows in the future. Also, in the future I suspect that polyfilling multidraw on APIs that don't support it will be fruitful, as even without driver-level support use of multidraw allows us to avoid expensive `wgpu` rebindings.
ecoskey
pushed a commit
to ecoskey/bevy
that referenced
this pull request
Jan 6, 2025
…y default. (bevyengine#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 (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**. ## 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.
Member
|
Thank you to everyone involved with the authoring or reviewing of this PR! This work is relatively important and needs release notes! Head over to bevyengine/bevy-website#1968 if you'd like to help out. |
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.
This commit adds support for multidraw, which is a feature that allows multiple meshes to be drawn in a single drawcall.
wgpucurrently implements multidraw on Vulkan, so this feature is only enabled there. Multiple meshes can be drawn at once if they're in the same vertex and index buffers and are otherwise placed in the same bin. (Thus, for example, at present the materials and textures must be identical, but see #16368.) Multidraw is a significant performance improvement during the draw phase because it reduces the number of rebindings, as well as the number of drawcalls.This feature is currently only enabled when GPU culling is used: i.e. when
GpuCullingis present on a camera. Therefore, if you run for examplescene_viewer, you will not see any performance improvements, becausescene_viewerdoesn't add theGpuCullingcomponent to its camera.Additionally, the multidraw feature is only implemented for opaque 3D meshes and not for shadows or 2D meshes. I plan to make GPU culling the default and to extend the feature to shadows in the future. Also, in the future I suspect that polyfilling multidraw on APIs that don't support it will be fruitful, as even without driver-level support use of multidraw allows us to avoid expensive
wgpurebindings.