bevy_core_pipeline/blit/
mod.rs1use bevy_app::{App, Plugin};
2use bevy_asset::{load_internal_asset, Handle};
3use bevy_ecs::prelude::*;
4use bevy_render::{
5 render_resource::{
6 binding_types::{sampler, texture_2d},
7 *,
8 },
9 renderer::RenderDevice,
10 RenderApp,
11};
12
13use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
14
15pub const BLIT_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(2312396983770133547);
16
17pub struct BlitPlugin;
19
20impl Plugin for BlitPlugin {
21 fn build(&self, app: &mut App) {
22 load_internal_asset!(app, BLIT_SHADER_HANDLE, "blit.wgsl", Shader::from_wgsl);
23
24 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
25 render_app.allow_ambiguous_resource::<SpecializedRenderPipelines<BlitPipeline>>();
26 }
27 }
28
29 fn finish(&self, app: &mut App) {
30 let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
31 return;
32 };
33 render_app
34 .init_resource::<BlitPipeline>()
35 .init_resource::<SpecializedRenderPipelines<BlitPipeline>>();
36 }
37}
38
39#[derive(Resource)]
40pub struct BlitPipeline {
41 pub texture_bind_group: BindGroupLayout,
42 pub sampler: Sampler,
43}
44
45impl FromWorld for BlitPipeline {
46 fn from_world(render_world: &mut World) -> Self {
47 let render_device = render_world.resource::<RenderDevice>();
48
49 let texture_bind_group = render_device.create_bind_group_layout(
50 "blit_bind_group_layout",
51 &BindGroupLayoutEntries::sequential(
52 ShaderStages::FRAGMENT,
53 (
54 texture_2d(TextureSampleType::Float { filterable: false }),
55 sampler(SamplerBindingType::NonFiltering),
56 ),
57 ),
58 );
59
60 let sampler = render_device.create_sampler(&SamplerDescriptor::default());
61
62 BlitPipeline {
63 texture_bind_group,
64 sampler,
65 }
66 }
67}
68
69#[derive(PartialEq, Eq, Hash, Clone, Copy)]
70pub struct BlitPipelineKey {
71 pub texture_format: TextureFormat,
72 pub blend_state: Option<BlendState>,
73 pub samples: u32,
74}
75
76impl SpecializedRenderPipeline for BlitPipeline {
77 type Key = BlitPipelineKey;
78
79 fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
80 RenderPipelineDescriptor {
81 label: Some("blit pipeline".into()),
82 layout: vec![self.texture_bind_group.clone()],
83 vertex: fullscreen_shader_vertex_state(),
84 fragment: Some(FragmentState {
85 shader: BLIT_SHADER_HANDLE,
86 shader_defs: vec![],
87 entry_point: "fs_main".into(),
88 targets: vec![Some(ColorTargetState {
89 format: key.texture_format,
90 blend: key.blend_state,
91 write_mask: ColorWrites::ALL,
92 })],
93 }),
94 primitive: PrimitiveState::default(),
95 depth_stencil: None,
96 multisample: MultisampleState {
97 count: key.samples,
98 ..Default::default()
99 },
100 push_constant_ranges: Vec::new(),
101 zero_initialize_workgroup_memory: false,
102 }
103 }
104}