1use wgpu::{
4 BindGroupLayout, ColorTargetState, ColorWrites, CompareFunction, DepthStencilState, Device,
5 FragmentState, PipelineLayoutDescriptor, PrimitiveState, PrimitiveTopology, RenderPipeline,
6 RenderPipelineDescriptor, ShaderModule, ShaderModuleDescriptor, ShaderSource, StencilState,
7 TextureFormat, VertexState,
8};
9
10use crate::mesh::{Vertex, Vertex3D};
11
12pub fn create_shader(device: &Device, source: &str, label: Option<&str>) -> ShaderModule {
13 match naga::front::wgsl::parse_str(source) {
15 Ok(_) => {}
16 Err(e) => {
17 tracing::warn!(
18 "Failed to parse WGSL source for '{}' during validation: {:?}",
19 label.unwrap_or("unnamed"),
20 e
21 );
22 }
23 }
24
25 device.create_shader_module(ShaderModuleDescriptor {
26 label,
27 source: ShaderSource::Wgsl(source.into()),
28 })
29}
30
31pub fn create_basic_pipeline(
32 device: &Device,
33 shader: &ShaderModule,
34 format: TextureFormat,
35) -> RenderPipeline {
36 let layout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
37 label: Some("Basic Pipeline Layout"),
38 bind_group_layouts: &[],
39 immediate_size: 0,
40 });
41
42 device.create_render_pipeline(&RenderPipelineDescriptor {
43 label: Some("Basic Pipeline"),
44 layout: Some(&layout),
45 vertex: VertexState {
46 module: shader,
47 entry_point: Some("vs_main"),
48 buffers: &[Vertex::desc()],
49 compilation_options: Default::default(),
50 },
51 fragment: Some(FragmentState {
52 module: shader,
53 entry_point: Some("fs_main"),
54 targets: &[Some(ColorTargetState {
55 format,
56 blend: None,
57 write_mask: ColorWrites::ALL,
58 })],
59 compilation_options: Default::default(),
60 }),
61 primitive: PrimitiveState {
62 topology: PrimitiveTopology::TriangleList,
63 strip_index_format: None,
64 front_face: wgpu::FrontFace::Ccw,
65 cull_mode: Some(wgpu::Face::Back),
66 polygon_mode: wgpu::PolygonMode::Fill,
67 unclipped_depth: false,
68 conservative: false,
69 },
70 depth_stencil: None,
71 multisample: wgpu::MultisampleState {
72 count: 1,
73 mask: !0,
74 alpha_to_coverage_enabled: false,
75 },
76 multiview_mask: None,
77 cache: None,
78 })
79}
80
81pub fn create_lit_pipeline(
82 device: &Device,
83 shader: &ShaderModule,
84 format: TextureFormat,
85 camera_layout: &BindGroupLayout,
86 material_layout: &BindGroupLayout,
87 light_layout: &BindGroupLayout,
88) -> RenderPipeline {
89 let layout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
90 label: Some("Lit Pipeline Layout"),
91 bind_group_layouts: &[camera_layout, material_layout, light_layout],
92 immediate_size: 0,
93 });
94
95 let depth_stencil = Some(DepthStencilState {
96 format: TextureFormat::Depth24PlusStencil8,
97 depth_write_enabled: true,
98 depth_compare: CompareFunction::Less,
99 stencil: StencilState::default(),
100 bias: wgpu::DepthBiasState::default(),
101 });
102
103 device.create_render_pipeline(&RenderPipelineDescriptor {
104 label: Some("Lit Pipeline"),
105 layout: Some(&layout),
106 vertex: VertexState {
107 module: shader,
108 entry_point: Some("vs_main"),
109 buffers: &[Vertex3D::desc()],
110 compilation_options: Default::default(),
111 },
112 fragment: Some(FragmentState {
113 module: shader,
114 entry_point: Some("fs_main"),
115 targets: &[Some(ColorTargetState {
116 format,
117 blend: None,
118 write_mask: ColorWrites::ALL,
119 })],
120 compilation_options: Default::default(),
121 }),
122 primitive: PrimitiveState {
123 topology: PrimitiveTopology::TriangleList,
124 strip_index_format: None,
125 front_face: wgpu::FrontFace::Ccw,
126 cull_mode: Some(wgpu::Face::Back),
127 polygon_mode: wgpu::PolygonMode::Fill,
128 unclipped_depth: false,
129 conservative: false,
130 },
131 depth_stencil,
132 multisample: wgpu::MultisampleState {
133 count: 1,
134 mask: !0,
135 alpha_to_coverage_enabled: false,
136 },
137 multiview_mask: None,
138 cache: None,
139 })
140}
141
142pub fn create_unlit_pipeline(
143 device: &Device,
144 shader: &ShaderModule,
145 format: TextureFormat,
146 camera_layout: &BindGroupLayout,
147 material_layout: &BindGroupLayout,
148) -> RenderPipeline {
149 let layout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
150 label: Some("Unlit Pipeline Layout"),
151 bind_group_layouts: &[camera_layout, material_layout],
152 immediate_size: 0,
153 });
154
155 let depth_stencil = Some(DepthStencilState {
156 format: TextureFormat::Depth24PlusStencil8,
157 depth_write_enabled: true,
158 depth_compare: CompareFunction::Less,
159 stencil: StencilState::default(),
160 bias: wgpu::DepthBiasState::default(),
161 });
162
163 device.create_render_pipeline(&RenderPipelineDescriptor {
164 label: Some("Unlit Pipeline"),
165 layout: Some(&layout),
166 vertex: VertexState {
167 module: shader,
168 entry_point: Some("vs_main"),
169 buffers: &[Vertex3D::desc()],
170 compilation_options: Default::default(),
171 },
172 fragment: Some(FragmentState {
173 module: shader,
174 entry_point: Some("fs_main"),
175 targets: &[Some(ColorTargetState {
176 format,
177 blend: None,
178 write_mask: ColorWrites::ALL,
179 })],
180 compilation_options: Default::default(),
181 }),
182 primitive: PrimitiveState {
183 topology: PrimitiveTopology::TriangleList,
184 strip_index_format: None,
185 front_face: wgpu::FrontFace::Ccw,
186 cull_mode: Some(wgpu::Face::Back),
187 polygon_mode: wgpu::PolygonMode::Fill,
188 unclipped_depth: false,
189 conservative: false,
190 },
191 depth_stencil,
192 multisample: wgpu::MultisampleState {
193 count: 1,
194 mask: !0,
195 alpha_to_coverage_enabled: false,
196 },
197 multiview_mask: None,
198 cache: None,
199 })
200}