Fix MSAA writeback when 3 or more cameras have the same target. (#11968)

# Objective

If multiple cameras render to the same target with MSAA enabled, only
the first and the last camera output will appear in the final output*.
This is because each camera maintains a separate flag to track the
active main texture. The first camera renders to texture A and all
subsequent cameras first write-back from A and then render into texture
B. Hence, camera 3 onwards will overwrite the work of the previous
camera.

\* This would manifest slightly differently if there were other calls to
post_process_write() in a more complex setup.

The is a functional regression from Bevy 0.12.

## Solution

The flag which tracks the active main texture should be shared between
cameras with the same `NormalizedRenderTarget`. Add the
`Arc<AtomicUsize>` to the existing per-target cache.
This commit is contained in:
Robin KAY 2024-02-20 22:16:28 +00:00 committed by François
parent 5d9c9b85d5
commit 152ee42a72

View file

@ -498,7 +498,7 @@ pub fn prepare_view_targets(
_ => Some(clear_color_global.0), _ => Some(clear_color_global.0),
}; };
let (a, b, sampled) = textures let (a, b, sampled, main_texture) = textures
.entry((camera.target.clone(), view.hdr)) .entry((camera.target.clone(), view.hdr))
.or_insert_with(|| { .or_insert_with(|| {
let descriptor = TextureDescriptor { let descriptor = TextureDescriptor {
@ -547,13 +547,14 @@ pub fn prepare_view_targets(
} else { } else {
None None
}; };
(a, b, sampled) let main_texture = Arc::new(AtomicUsize::new(0));
(a, b, sampled, main_texture)
}); });
let main_textures = MainTargetTextures { let main_textures = MainTargetTextures {
a: ColorAttachment::new(a.clone(), sampled.clone(), clear_color), a: ColorAttachment::new(a.clone(), sampled.clone(), clear_color),
b: ColorAttachment::new(b.clone(), sampled.clone(), clear_color), b: ColorAttachment::new(b.clone(), sampled.clone(), clear_color),
main_texture: Arc::new(AtomicUsize::new(0)), main_texture: main_texture.clone(),
}; };
commands.entity(entity).insert(ViewTarget { commands.entity(entity).insert(ViewTarget {