bevy_shader_plugin/
pipeline.rs1use std::collections::HashMap;
2
3use bevy::{
4 asset::AssetServer,
5 core_pipeline::FullscreenShader,
6 prelude::*,
7 render::{
8 render_resource::{
9 BindGroupLayout, BlendState, CachedRenderPipelineId, ColorTargetState, ColorWrites,
10 FragmentState, MultisampleState, PipelineCache, RenderPipelineDescriptor,
11 TextureFormat,
12 },
13 view::ExtractedView,
14 },
15};
16
17use crate::{FragmentExtraLayouts, bindings::AutoBufferLayoutDescriptors};
18
19#[derive(Resource)]
22pub struct FullscreenPipelineConfig {
23 pub shader_path: &'static str,
24 pub entry_point: Option<&'static str>,
25}
26
27#[derive(Resource)]
32pub struct FullscreenPipeline {
33 descriptor: RenderPipelineDescriptor,
35 pipelines: HashMap<TextureFormat, CachedRenderPipelineId>,
36 pub extra_layouts: Vec<BindGroupLayout>,
39}
40
41impl FullscreenPipeline {
42 pub fn pipeline_id(&self, format: TextureFormat) -> Option<CachedRenderPipelineId> {
44 self.pipelines.get(&format).copied()
45 }
46}
47
48pub(crate) fn init_pipeline(
52 mut commands: Commands,
53 asset_server: Res<AssetServer>,
54 fullscreen_shader: Res<FullscreenShader>,
55 pipeline_cache: Res<PipelineCache>,
56 config: Res<FullscreenPipelineConfig>,
57 extra_layouts: Res<FragmentExtraLayouts>,
58 auto_buffer_descriptors: Res<AutoBufferLayoutDescriptors>,
59) {
60 let mut all_layouts = auto_buffer_descriptors.0.clone();
61 all_layouts.extend(extra_layouts.0.iter().cloned());
62
63 let descriptor = RenderPipelineDescriptor {
64 label: Some("fullscreen_fragment_pipeline".into()),
65 layout: all_layouts,
66 vertex: fullscreen_shader.to_vertex_state(),
67 fragment: Some(FragmentState {
68 shader: asset_server.load(config.shader_path),
69 entry_point: config.entry_point.map(Into::into),
70 targets: Vec::new(),
72 ..default()
73 }),
74 multisample: MultisampleState {
75 count: 1,
76 mask: !0,
77 alpha_to_coverage_enabled: false,
78 },
79 ..default()
80 };
81
82 let extra_compiled: Vec<BindGroupLayout> = extra_layouts
83 .0
84 .iter()
85 .map(|desc| pipeline_cache.get_bind_group_layout(desc))
86 .collect();
87
88 commands.insert_resource(FullscreenPipeline {
89 descriptor,
90 pipelines: HashMap::new(),
91 extra_layouts: extra_compiled,
92 });
93}
94
95pub(crate) fn queue_fullscreen_pipelines(
97 pipeline: Option<ResMut<FullscreenPipeline>>,
98 pipeline_cache: Res<PipelineCache>,
99 views: Query<&ExtractedView>,
100) {
101 let Some(mut pipeline) = pipeline else {
102 return;
103 };
104 for view in &views {
105 let format = view.target_format;
106 if pipeline.pipelines.contains_key(&format) {
107 continue;
108 }
109 let mut descriptor = pipeline.descriptor.clone();
110 if let Some(fragment) = &mut descriptor.fragment {
111 fragment.targets = vec![Some(ColorTargetState {
112 format,
113 blend: Some(BlendState::ALPHA_BLENDING),
114 write_mask: ColorWrites::ALL,
115 })];
116 }
117 let id = pipeline_cache.queue_render_pipeline(descriptor);
118 pipeline.pipelines.insert(format, id);
119 }
120}