Fix blending for CameraOutputMode::Skip (#16157)

# Objective

Currently, if we have two cameras with the same output texture, one with
`CameraOutputMode::Write` and one with `CameraOutputMode::Skip`, it is
possible for the `CameraOutputMode::Write` camera to be assigned alpha
blending (which is the fallback blending when multiple cameras write to
the same output texture), although it is the only camera writing to the
output texture. This may or may not happen every restart of the app,
because the camera iteration order in prepare_view_upscaling_pipelines
isn't consistent. Since this is random behaviour I consider this a bug
and didn't add a migration guide.

## Solution

In `prepare_view_upscaling_pipelines` make sure we don't consider
cameras with CameraOutputMode::Skip to be outputting something to the
output texture.

## Testing

I ran a few examples to make sure nothing obvious is broken. There is no
example using CameraOutputMode::Skip, so I only tested the change in my
own App where this was relevant, which however isn't public.
This commit is contained in:
Lennard 2024-11-04 16:26:42 +01:00 committed by GitHub
parent a9b2344992
commit cd2d14c0fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -46,28 +46,32 @@ fn prepare_view_upscaling_pipelines(
let mut output_textures = HashSet::new(); let mut output_textures = HashSet::new();
for (entity, view_target, camera) in view_targets.iter() { for (entity, view_target, camera) in view_targets.iter() {
let out_texture_id = view_target.out_texture().id(); let out_texture_id = view_target.out_texture().id();
let blend_state = if let Some(ExtractedCamera { let blend_state = if let Some(extracted_camera) = camera {
output_mode: CameraOutputMode::Write { blend_state, .. }, match extracted_camera.output_mode {
.. CameraOutputMode::Skip => None,
}) = camera CameraOutputMode::Write { blend_state, .. } => {
{ let already_seen = output_textures.contains(&out_texture_id);
match *blend_state { output_textures.insert(out_texture_id);
None => {
// If we've already seen this output for a camera and it doesn't have a output blend match blend_state {
// mode configured, default to alpha blend so that we don't accidentally overwrite None => {
// the output texture // If we've already seen this output for a camera and it doesn't have a output blend
if output_textures.contains(&out_texture_id) { // mode configured, default to alpha blend so that we don't accidentally overwrite
Some(BlendState::ALPHA_BLENDING) // the output texture
} else { if already_seen {
None Some(BlendState::ALPHA_BLENDING)
} else {
None
}
}
_ => blend_state,
} }
} }
_ => *blend_state,
} }
} else { } else {
output_textures.insert(out_texture_id);
None None
}; };
output_textures.insert(out_texture_id);
let key = BlitPipelineKey { let key = BlitPipelineKey {
texture_format: view_target.out_texture_format(), texture_format: view_target.out_texture_format(),