Skip to content

Fix msaa writeback prevents clear color - #25634

Open
beicause wants to merge 14 commits into
bevyengine:mainfrom
beicause:msaa-writeback-clear-fix
Open

Fix msaa writeback prevents clear color#25634
beicause wants to merge 14 commits into
bevyengine:mainfrom
beicause:msaa-writeback-clear-fix

Conversation

@beicause

@beicause beicause commented Sep 1, 2026

Copy link
Copy Markdown
Member

Objective

Fixes #22453, extracted from #25226

Solution

Only run msaa writeback if camera clear color config is None.

It's OK because camera with LoadOp::Clear will clear the entire main texture thus writeback is useless.

Testing

Run the example in #22453

@beicause beicause added C-Bug An unexpected or incorrect behavior A-Rendering Drawing game state to the screen S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Sep 1, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in Rendering Sep 1, 2026
@beicause
beicause force-pushed the msaa-writeback-clear-fix branch from 46a4e02 to acff97f Compare September 1, 2026 19:29

@stuartparmenter stuartparmenter 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.

This looks right to me. Writeback only matters when the camera has ClearColorConfig::None, my check in #25479 was doing this the complicated way. I was looking at this further after that PR, but hadn't had a chance to file an issue or PR yet --

Can you look at these 3 things?

  1. Don't call mark_as_cleared on the destination in the writeback. Nothing depends on it, and it's what causes the camera's clear to turn into a load. Removing it also fixes MsaaWriteback::Always, which drops the clear color today.
  2. Fix the examples relying on the old behavior: first_person_view_model, loading_screen, and ui_target_camera. Each has a fullscreen camera on top with a default clear color, so with this change the top camera hides everything below it. Set ClearColorConfig::None on those cameras, and remove the comment in ui_target_camera that says only the lowest camera clears.
  3. Add a migration guide

@beicause
beicause force-pushed the msaa-writeback-clear-fix branch from ce59a72 to 57186bf Compare September 1, 2026 23:58
Comment thread crates/bevy_post_process/src/msaa_writeback.rs Outdated
@beicause

beicause commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

I made MSAA writeback never run if camera is not ClearColorConfig::None so we don't need to avoid ViewTarget::mark_as_cleared

loading_screen doesn't need ClearColorConfig::None because it draws a fullscreen black Node.

@stuartparmenter

stuartparmenter commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

I made MSAA writeback never run if camera is not ClearColorConfig::None so we don't need to avoid ViewTarget::mark_as_cleared

loading_screen doesn't need ClearColorConfig::None because it draws a fullscreen black Node.

Thanks, gating on clear_color == None is a fine way to handle mark_as_cleared, works for me.

A few things left:

  1. loading_screen still needs ClearColorConfig::None on the UI camera. The fullscreen black node gets hidden once the level is ready, but the camera keeps rendering with the default clear color and wipes the 3D scene every frame. It only works today because writeback was turning that clear into a load.
  2. I don't think your change from Auto being clear_color == None to sorted_camera_index_for_target > 0 && clear_color == None is right. It undoes part of Make ClearColorConfig::None work correctly (esp in the presence of MSAA) #23844 where a single camera with None and MSAA on no longer writes back, so it loses what it rendered last frame. Since clear_color == None is already required for any writeback, Auto can just be true. The Auto docs and the comment in prepare_msaa_writeback_pipelines say the first camera has nothing to write back, which isn't right either.
  3. ui_target_camera: I'd just drop the "cleared according to the camera with the lowest order" comment. The engine doesn't do that, it only looks that way because the observer reassigns every camera's clear color.

@beicause

This comment was marked as resolved.

Comment thread examples/ui/ui_target_camera.rs Outdated
Comment thread examples/ui/ui_target_camera.rs Outdated
@stuartparmenter

Copy link
Copy Markdown
Contributor
  1. For the loading screen, the UI camera does not need any 3D scene content at all; in this case, LoadOp::Clear will have better performance than LoadOp::Load which is unnecessary.

I ran loading_screen on your branch and after the level loads I get a blank grey screen instead of the fox I see on main. The UI camera doesn't read the 3D content, but it's drawn into the same main texture and then alpha-blended over the window. The default clear color is opaque, so the clear covers the scene. Setting ClearColorConfig::None on that camera brings the fox back.

  1. "a single camera with None and MSAA on no longer writes back" is exactly the difference between Auto and Always.

Auto skipping the first camera was the behavior before #23844. It seems like that PR added the None case to Auto because a single camera with ClearColorConfig::None and MSAA was throwing away its main texture, so your change would be reverting that fix. I'd rather Auto stay correct by default and Always be the odd one out, but maybe @tychedelia has an opinion here?

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-Bug An unexpected or incorrect behavior 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.

MSAA changes camera ordering.

2 participants