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