bevy_core_pipeline/upscaling/
mod.rs1use crate::blit::{BlitPipeline, BlitPipelineKey};
2use bevy_app::prelude::*;
3use bevy_camera::CameraOutputMode;
4use bevy_ecs::prelude::*;
5use bevy_render::{
6 camera::ExtractedCamera, render_resource::*, view::ViewTarget, Render, RenderApp,
7 RenderStartup, RenderSystems,
8};
9
10mod node;
11
12pub use node::upscaling;
13
14pub struct UpscalingPlugin;
15
16impl Plugin for UpscalingPlugin {
17 fn build(&self, app: &mut App) {
18 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
19 render_app.add_systems(
20 Render,
21 prepare_view_upscaling_pipelines
27 .in_set(RenderSystems::Prepare)
28 .ambiguous_with_all(),
29 );
30 render_app.add_systems(RenderStartup, clear_view_upscaling_pipelines);
31 }
32 }
33}
34
35#[derive(Component)]
36pub struct ViewUpscalingPipeline(CachedRenderPipelineId, BlitPipelineKey);
37
38fn clear_view_upscaling_pipelines(
40 mut commands: Commands,
41 views: Query<Entity, With<ViewUpscalingPipeline>>,
42) {
43 for entity in &views {
44 commands.entity(entity).remove::<ViewUpscalingPipeline>();
45 }
46}
47
48fn prepare_view_upscaling_pipelines(
49 mut commands: Commands,
50 mut pipeline_cache: ResMut<PipelineCache>,
51 mut pipelines: ResMut<SpecializedRenderPipelines<BlitPipeline>>,
52 blit_pipeline: Res<BlitPipeline>,
53 view_targets: Query<(
54 Entity,
55 &ViewTarget,
56 Option<&ExtractedCamera>,
57 Option<&ViewUpscalingPipeline>,
58 )>,
59) {
60 for (entity, view_target, camera, maybe_pipeline) in view_targets.iter() {
61 let blend_state = if let Some(extracted_camera) = camera {
62 match extracted_camera.output_mode {
63 CameraOutputMode::Skip => None,
64 CameraOutputMode::Write { blend_state, .. } => {
65 match blend_state {
66 None => {
67 if extracted_camera.sorted_camera_index_for_target > 0 {
72 Some(BlendState::ALPHA_BLENDING)
73 } else {
74 None
75 }
76 }
77 _ => blend_state,
78 }
79 }
80 }
81 } else {
82 None
83 };
84
85 let Some(target_format) = view_target.out_texture_view_format() else {
86 continue;
87 };
88
89 let key = BlitPipelineKey {
90 target_format,
91 blend_state,
92 samples: 1,
93 source_space: view_target.compositing_space,
94 };
95
96 if maybe_pipeline.is_none_or(|ViewUpscalingPipeline(_, cached_key)| *cached_key != key) {
97 let pipeline = pipelines.specialize(&pipeline_cache, &blit_pipeline, key);
98
99 pipeline_cache.block_on_render_pipeline(pipeline);
102
103 commands
104 .entity(entity)
105 .insert(ViewUpscalingPipeline(pipeline, key));
106 }
107 }
108}