Skip to content

Skip dynamic cluster resizing when GPU clustering is active#23439

Open
holg wants to merge 3 commits into
bevyengine:mainfrom
holg:fix/cluster-dynamic-resize-gpu
Open

Skip dynamic cluster resizing when GPU clustering is active#23439
holg wants to merge 3 commits into
bevyengine:mainfrom
holg:fix/cluster-dynamic-resize-gpu

Conversation

@holg

@holg holg commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

Objective

Fixes #23438

The dynamic resizing code in assign_objects_to_clusters compares last frame's cluster index count against
ViewClusterBindings::MAX_INDICES (16384), which is the UBO limit. When GPU clustering (#23036) is active, storage
buffers are used and can hold far more indices. The resizing shrinks the grid unnecessarily, causing thrashing and
flickering.

#22874 added dynamic resizing before GPU clustering existed, so the UBO limit was correct. When #23036 landed, the
runtime index path was updated to skip the limit when storage buffers are available (line 500 in cluster/mod.rs), but
the dynamic resizing path was not.

Solution

Skip the dynamic resizing when global_cluster_settings.gpu_clustering is active.

// Skip when storage buffers are available
if config.dynamic_resizing()
    && !global_cluster_settings.supports_storage_buffers
    && let Some(last_frame_cluster_index_count) = ...

Testing

  • Tested on Apple M2 Max (Metal), NVIDIA 5060 Ti (Vulkan), Intel i360P (Vulkan)
  • Also tested via WASM/WebGPU in Chrome on macOS and Windows
  • Flickering resolved in scenes with many clustered lights
  • No change when GPU clustering is disabled — existing UBO path unaffected

Copilot AI review requested due to automatic review settings March 20, 2026 20:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR prevents clustered-light grid “dynamic resizing” from running when GPU clustering is enabled, avoiding unnecessary cluster-grid shrinking based on the uniform-buffer index limit and reducing flicker/thrashing in heavy clustered-light scenes.

Changes:

  • Add a guard to skip dynamic resizing logic when global_cluster_settings.gpu_clustering is active.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// If the dynamic resizing feature is on, use the last frame's cluster
// index count to determine the new number of clusters.
// Skip when GPU clustering is active
if config.dynamic_resizing()

Copilot AI Mar 20, 2026

Copy link

Choose a reason for hiding this comment

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

The dynamic resizing guard is currently tied to gpu_clustering.is_none(), but the index-list limit it’s trying to avoid (ViewClusterBindings::MAX_INDICES) is only enforced when supports_storage_buffers is false (see crates/bevy_pbr/src/cluster/mod.rs around the n_indices() >= MAX_INDICES && !supports_storage_buffers check). On devices where compute shaders are unavailable (so gpu_clustering is None) but storage buffers are supported, this will still shrink clusters unnecessarily. Consider gating dynamic resizing on !global_cluster_settings.supports_storage_buffers (or otherwise using an “effective max indices” value that reflects whether storage buffers are in use).

Suggested change
if config.dynamic_resizing()
if config.dynamic_resizing()
&& !global_cluster_settings.supports_storage_buffers

Copilot uses AI. Check for mistakes.
The UBO index limit (16384) doesn't apply when using storage buffers.
@holg holg force-pushed the fix/cluster-dynamic-resize-gpu branch from 4c446c3 to c5574e1 Compare March 20, 2026 21:59
@holg

holg commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

changed to :
// Skip when storage buffers are available
if config.dynamic_resizing()
&& !global_cluster_settings.supports_storage_buffers

@kfc35 kfc35 added A-Rendering Drawing game state to the screen S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 20, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in Rendering Mar 20, 2026
@kfc35 kfc35 added the C-Performance A change motivated by improving speed, memory usage or compile times label Mar 20, 2026
@JMS55 JMS55 requested a review from pcwalton March 21, 2026 02:18
@holg holg mentioned this pull request Mar 22, 2026
1 task
@pcwalton

pcwalton commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Going through my review queue. Is this still relevant/should I review it?

@holg

holg commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Yes, still relevant:
the issue is still present on current main: the dynamic resizing block in assign_objects_to_clusters (crates/bevy_light/src/cluster/assign.rs) still shrinks the cluster grid against the 16384 UBO limit unconditionally,
while the runtime index path in the same file already skips that limit when storage buffers are available.
So with GPU clustering active the grid still gets resized down needlessly, causing the thrashing/flickering described in #23438.
as well it would help my bevy related crates to be pushed onto crates.io (eulumdat-bevy and gldf-bevy) , as i am relying on this... (right now they need my own fork, so i cannot publish)

@pcwalton pcwalton left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I’m a little unsure about whether we shouldn’t have any limit, because clusters do have a cost, but I guess this at least makes it consistent.


// If the dynamic resizing feature is on, use the last frame's cluster
// index count to determine the new number of clusters.
// Skip when storage buffers are available

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Skip when storage buffers are available
// We don’t need to do this if storage buffers are available, because we have plenty of space in that case.

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 S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

Dynamic cluster resizing incorrectly uses UBO limit when GPU clustering is active

5 participants