MacOS Rendering Corruption starting on 0.19.0
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## Bevy version and features
- Bevy 0.19.1, 0.19.0 (not reproducible in 0.18.1)
- Default features
## \[Optional\] Relevant system information
If your bug is rendering-related, copy the adapter info that appears when you run Bevy.
```ignore
AdapterInfo { name: "Apple M3 Pro", vendor: 0, device: 0, device_type: IntegratedGpu, device_pci_bus_id: "", driver: "", driver_info: "", backend: Metal, subgroup_min_size: 4, subgroup_max_size: 64, transient_saves_memory: true }
```
## What you did
I'm encountering a combination of 2 issues:
- Materials that swapping around to different meshes
- Meshes flickering in and out of visibility, every other frame
It happens under these circumstances, but I haven't been able to narrow it down specifically:
- Only impacts 0.19.x versions
- Impacts macOS, does not impact Windows
- Only happens with GPU Preprocessing - I think this is a strong clue about the root cause, see the bottom for more information
- The problem gets worse using:
- GLTF Meshes (I'm relying on instancing a lot)
- FXAA instead of MSAA
I'm working really hard to get a minimal reproducible build, But I haven't been successful. The problem seems to scale with complexity, so I think you need a complicated rendering setup to get the issue to trigger. I would be willing to share my reproduction with select maintainers if requested.
## What went wrong
Here's a video of the corruption:
https://github.com/user-attachments/assets/1ea5b0a1-3ba9-4577-86c7-5dfed40ae163
## Additional information
### Theory About GPU Preprocessing
I'm able to fix the issue by forcing the WGPU to use CPU preprocessing. This changes the log `GPU preprocessing is fully supported on this device.` to `(GPU preprocessing is not supported on this device. Falling back to CPU preprocessing.),`. When I do this, my framerate improves, and the flickering and material swapping goes away entirely.
**Hunches**: I am not super knowledgeable about WGPU internals, but doing some research, here's some thoughts:
- I tried setting `WgpuSettings::disabled_features(WgpuFeatures::TEXTURE_BINDING_ARRAY)`, thinking the issue was related to bindless textures, but this didn't solve it
- I think the issue lies in the GPU indirect drawing path that GPU preprocessing/culling turns on.
- I'm thinking this could be related to #21739, AlphaMode::Blend meshes flickering with indirect drawing
- [I did some AI-assisted digging here] There was a change between 0.18 and 0.19 where MeshAllocator's slab-resize still does a queue.submit that never joined the new batched PendingCommandBuffers model everything else in the render graph now goes through, so there's one remaining out-of-band submission in an otherwise fully-batched frame
Here's the workaround that fixes the issue even on 0.19.1:
```rust
let render_plugin = bevy::render::RenderPlugin {
render_creation: macos_wgpu_settings_forcing_cpu_preprocessing().into(),
..default()
};
app.add_plugins((DefaultPlugins.set(render_plugin),...));
...
// Hack to disable GPU preprocessing on macOS
#[cfg(target_os = "macos")]
fn macos_wgpu_settings_forcing_cpu_preprocessing() -> bevy::render::settings::WgpuSettings {
use bevy::render::settings::WgpuLimits;
bevy::render::settings::WgpuSettings {
constrained_limits: Some(
WgpuLimits {
max_binding_array_elements_per_shader_stage: u32::MAX,
max_binding_array_sampler_elements_per_shader_stage: u32::MAX,
..WgpuLimits::downlevel_webgl2_defaults()
}
.using_resolution(WgpuLimits::default()),
),
..default()
}
}
```
Contributor guide
Research direction
Start with the reported reproduction conditions: Bevy 0.19.x on macOS with an Apple Metal GPU and GPU preprocessing enabled, then compare against the CPU-preprocessing workaround. Inspect the RenderPlugin/WgpuSettings entry points, MeshAllocator slab resizing, and the indirect drawing path; done means identifying and fixing the corruption so meshes no longer flicker or swap materials.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- computer-graphics, game-dev
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100