easy_gpu/assets/render/
pipeline.rs1use 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}