Skip to main content

easy_gpu/assets/render/
pipeline.rs

1use wgpu::{BlendState, BufferBindingType, Device, SurfaceConfiguration};
2use wgpu::ShaderModule;
3use crate::assets::vertex_layout::BufferLayout;
4use crate::assets_manager::asset_manager::AssetManager;
5use crate::assets_manager::handle::Handle;
6
7pub struct RenderPipeline {
8    pub pipeline: wgpu::RenderPipeline,
9    pub material_layout: wgpu::BindGroupLayout,
10}
11
12pub struct RenderPipelineBuilder<'a> {
13    shader: Handle<ShaderModule>,
14    vertex_layouts: Vec<wgpu::VertexBufferLayout<'a>>,
15    pub(crate) depth_format: Option<wgpu::TextureFormat>,
16    depth_writes_enabled: bool,
17    material_entries: Vec<wgpu::BindGroupLayoutEntry>,
18    blend: BlendState,
19}
20
21impl<'a> RenderPipelineBuilder<'a> {
22    pub fn new(
23        shader: Handle<ShaderModule>,
24    ) -> Self {
25        Self {
26            shader,
27            vertex_layouts: Vec::new(),
28            depth_format: None,
29            depth_writes_enabled: true,
30            material_entries: vec![],
31            blend: BlendState::ALPHA_BLENDING,
32        }
33    }
34    pub fn material_layout(
35        mut self,
36        entries: &[wgpu::BindGroupLayoutEntry],
37    ) -> Self {
38        self.material_entries = entries.to_vec();
39        self
40    }
41
42    pub fn vertex_layout(mut self, layout: BufferLayout) -> Self {
43        self.vertex_layouts.push(layout.to_wgpu_layout());
44        self
45    }
46
47    pub fn depth_format(mut self, format: wgpu::TextureFormat) -> Self {
48        self.depth_format = Some(format);
49        self
50    }
51
52    pub fn depth_writes_enabled(mut self, enabled: bool) -> Self {
53        self.depth_writes_enabled = enabled;
54        self
55    }
56    
57    pub fn additive_alpha_blending(mut self) -> Self{
58        self.blend = wgpu::BlendState {
59            color:wgpu::BlendComponent {
60                src_factor: wgpu::BlendFactor::SrcAlpha,
61                dst_factor: wgpu::BlendFactor::One,
62                operation: wgpu::BlendOperation::Add,
63            },
64            alpha: wgpu::BlendComponent {
65                src_factor: wgpu::BlendFactor::One,
66                dst_factor: wgpu::BlendFactor::One,
67                operation: wgpu::BlendOperation::Add,
68            }};
69        self
70    }
71
72    pub fn blend_mode(mut self,blend_state: BlendState) -> Self{
73        self.blend = blend_state;
74        self
75    }
76
77    pub fn build(self,device: &Device,asset_manager: &AssetManager,surface_config: &SurfaceConfiguration) -> RenderPipeline {
78        let shader = asset_manager.shaders.get(self.shader).unwrap();
79
80        let material_layout = device.create_bind_group_layout(
81            &wgpu::BindGroupLayoutDescriptor {
82                label: Some("material layout"),
83                entries: &self.material_entries,
84            }
85        );
86
87        let pipeline_layout = device.create_pipeline_layout(
88            &wgpu::PipelineLayoutDescriptor {
89                label: Some("pipeline layout"),
90                bind_group_layouts: &[
91                    Some(&material_layout),
92                ],
93                immediate_size: 0,
94            }
95        );
96
97        let pipeline = device.create_render_pipeline(
98            &wgpu::RenderPipelineDescriptor {
99                label: Some("pipeline"),
100                layout: Some(&pipeline_layout),
101                vertex: wgpu::VertexState {
102                    module: shader,
103                    entry_point: Option::from("vs_main"),
104                    compilation_options: Default::default(),
105                    buffers: &self.vertex_layouts,
106                },
107                fragment: Some(wgpu::FragmentState {
108                    module: shader,
109                    entry_point: Option::from("fs_main"),
110                    compilation_options: Default::default(),
111                    targets: &[Some(wgpu::ColorTargetState {
112                        format: surface_config.format,
113                        blend: Some(self.blend),
114                        write_mask: wgpu::ColorWrites::ALL,
115                    })],
116                }),
117                multiview_mask: None,
118                primitive: wgpu::PrimitiveState::default(),
119                depth_stencil: self.depth_format.map(|format| {
120                    wgpu::DepthStencilState {
121                        format,
122                        depth_write_enabled: Option::from(self.depth_writes_enabled),
123                        depth_compare: Option::from(wgpu::CompareFunction::LessEqual),
124                        stencil: Default::default(),
125                        bias: Default::default(),
126                    }
127                }),
128                multisample: wgpu::MultisampleState::default(),
129                cache: None,
130            }
131        );
132
133        RenderPipeline { pipeline, material_layout }
134    }
135}
136
137pub fn texture(binding: u32) -> wgpu::BindGroupLayoutEntry {
138    wgpu::BindGroupLayoutEntry {
139        binding,
140        visibility: wgpu::ShaderStages::FRAGMENT,
141        ty: wgpu::BindingType::Texture {
142            multisampled: false,
143            view_dimension: wgpu::TextureViewDimension::D2,
144            sample_type: wgpu::TextureSampleType::Float { filterable: true },
145        },
146        count: None,
147    }
148}
149
150pub fn sampler(binding: u32) -> wgpu::BindGroupLayoutEntry {
151    wgpu::BindGroupLayoutEntry {
152        binding,
153        visibility: wgpu::ShaderStages::FRAGMENT,
154        ty: wgpu::BindingType::Sampler(
155            wgpu::SamplerBindingType::Filtering
156        ),
157        count: None,
158    }
159}
160
161pub fn uniform(binding: u32) -> wgpu::BindGroupLayoutEntry {
162    wgpu::BindGroupLayoutEntry {
163        binding,
164        visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
165        ty: wgpu::BindingType::Buffer {
166            ty: BufferBindingType::Uniform,
167            has_dynamic_offset: false,
168            min_binding_size: None,
169        },
170        count: None,
171    }
172}