1use crate::colour::Colour;
20use crate::context::WgpuClump;
21use crate::engine_handle::Engine;
22use crate::resource::{ResourceId, ResourceManager};
23use crate::shader::Shader;
24use crate::texture::UniformTexture;
25use crate::vectors::Vec2;
26use crate::{vec2, Game};
27
28pub(crate) fn make_pipeline(
29 device: &wgpu::Device,
30 topology: wgpu::PrimitiveTopology,
31 bind_group_layouts: &[&wgpu::BindGroupLayout],
32 vertex_buffers: &[wgpu::VertexBufferLayout],
33 shader: &wgpu::ShaderModule,
34 texture_format: wgpu::TextureFormat,
35 label: Option<&str>,
36) -> wgpu::RenderPipeline {
37 let layout_label = label.map(|label| format!("{}_layout", label));
38
39 let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
40 label: layout_label.as_deref(), bind_group_layouts,
42 push_constant_ranges: &[],
43 });
44
45 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
46 label,
47 layout: Some(&layout),
48 vertex: wgpu::VertexState {
49 module: shader,
50 entry_point: "vs_main", buffers: vertex_buffers, compilation_options: wgpu::PipelineCompilationOptions::default(),
53 },
54 fragment: Some(wgpu::FragmentState {
55 module: shader,
57 entry_point: "fs_main",
58 targets: &[Some(wgpu::ColorTargetState {
59 format: texture_format,
61 blend: Some(wgpu::BlendState::ALPHA_BLENDING), write_mask: wgpu::ColorWrites::ALL, })],
64 compilation_options: wgpu::PipelineCompilationOptions::default(),
65 }),
66 primitive: wgpu::PrimitiveState {
67 topology,
68 strip_index_format: None,
69 front_face: wgpu::FrontFace::Cw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill,
73 unclipped_depth: false,
75 conservative: false,
77 },
78 depth_stencil: None,
79 multisample: wgpu::MultisampleState {
80 count: 1, mask: !0, alpha_to_coverage_enabled: false, },
84 multiview: None,
85 cache: None,
86 })
87}
88
89pub(crate) fn render<T>(game: &mut T, engine: &mut Engine) -> Result<(), wgpu::SurfaceError>
98where
99 T: Game,
100{
101 if engine.is_loading() {
103 return Ok(());
104 }
105
106 let render_handle = RenderHandle::from(engine);
107
108 game.render(render_handle);
109
110 Ok(())
111}
112
113pub struct RenderHandle<'a> {
115 encoder: Option<wgpu::CommandEncoder>,
117 surface: Option<wgpu::SurfaceTexture>,
118 pub(crate) resources: &'a ResourceManager,
119 defualt_id: ResourceId<Shader>,
120 defualt_view: wgpu::TextureView,
121 defualt_view_size: Vec2<u32>,
122 camera_bindgroup: &'a wgpu::BindGroup,
123 pub(crate) wgpu: &'a WgpuClump,
124 format: wgpu::TextureFormat,
125}
126
127impl<'a> RenderHandle<'a> {
128 pub fn begin_pass<'p>(&mut self, clear_colour: Colour) -> Renderer<'_, 'p> {
130 let mut pass = match &mut self.encoder {
131 Some(encoder) => Self::create_pass(encoder, &self.defualt_view, clear_colour.into()),
132 None => unreachable!(),
133 };
134
135 let pipeline = &self
136 .resources
137 .get_pipeline(&self.defualt_id)
138 .unwrap()
139 .pipeline;
140
141 pass.set_pipeline(pipeline);
142 pass.set_bind_group(1, self.camera_bindgroup, &[]);
143
144 Renderer {
145 pass,
146 size: self.defualt_view_size,
147 defualt_id: self.defualt_id,
148 resources: self.resources,
149 camera_bindgroup: self.camera_bindgroup,
150 wgpu: self.wgpu,
151 }
152 }
153
154 pub fn begin_texture_pass<'o, 'p>(
158 &'o mut self,
159 texture: &'o mut UniformTexture,
160 clear_colour: Colour,
161 ) -> Renderer<'o, 'p> {
162 let size = texture.get_size();
163
164 let mut pass = match &mut self.encoder {
165 Some(encoder) => Self::create_pass(
166 encoder,
167 texture.make_render_view(self.wgpu, self.format),
168 clear_colour.into(),
169 ),
170 None => unreachable!(),
171 };
172
173 let pipeline = &self
174 .resources
175 .get_pipeline(&self.defualt_id)
176 .unwrap()
177 .pipeline;
178
179 pass.set_pipeline(pipeline);
180 pass.set_bind_group(1, self.camera_bindgroup, &[]);
181
182 Renderer {
183 pass,
184 size,
185 defualt_id: self.defualt_id,
186 resources: self.resources,
187 camera_bindgroup: self.camera_bindgroup,
188 wgpu: self.wgpu,
189 }
190 }
191
192 fn create_pass<'p>(
193 encoder: &'p mut wgpu::CommandEncoder,
194 view: &'p wgpu::TextureView,
195 clear_colour: wgpu::Color,
196 ) -> wgpu::RenderPass<'p> {
197 let render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
198 label: Some("Render Pass"),
199 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
200 view,
201 resolve_target: None,
202 ops: wgpu::Operations {
203 load: wgpu::LoadOp::Clear(clear_colour),
204 store: wgpu::StoreOp::Store,
205 },
206 })],
207 timestamp_writes: None,
208 occlusion_query_set: None,
209 depth_stencil_attachment: None,
210 });
211
212 render_pass
213 }
214}
215
216impl<'a> From<&'a mut Engine> for RenderHandle<'a> {
217 fn from(value: &'a mut Engine) -> Self {
218 let context = value.context.as_ref().unwrap();
219
220 let encoder = context
221 .wgpu
222 .device
223 .create_command_encoder(&wgpu::CommandEncoderDescriptor {
224 label: Some("render encoder"),
225 });
226
227 let texture = context.get_surface_texture().unwrap();
228
229 let defualt_view_size = texture.texture.size();
230 let defualt_view_size = vec2!(defualt_view_size.width, defualt_view_size.height);
231 let defualt_view = texture
232 .texture
233 .create_view(&wgpu::TextureViewDescriptor::default());
234
235 Self {
236 encoder: Some(encoder),
237 surface: Some(texture),
238 resources: value.get_resources(),
239 defualt_id: value.defualt_pipe_id(),
240 defualt_view,
241 defualt_view_size,
242 camera_bindgroup: &context.camera_bind_group,
243 wgpu: &context.wgpu,
244 format: context.get_texture_format(),
245 }
246 }
247}
248
249impl Drop for RenderHandle<'_> {
250 fn drop(&mut self) {
251 self.wgpu
252 .queue
253 .submit(std::iter::once(self.encoder.take().unwrap().finish()));
254
255 self.surface.take().unwrap().present();
256 }
257}
258
259pub struct Renderer<'o, 'p>
262where
263 'o: 'p,
264{
265 pub(crate) pass: wgpu::RenderPass<'p>,
266 pub(crate) size: Vec2<u32>,
267 pub(crate) resources: &'o ResourceManager,
268 pub(crate) defualt_id: ResourceId<Shader>,
269 pub(crate) camera_bindgroup: &'o wgpu::BindGroup,
270 pub(crate) wgpu: &'o WgpuClump,
271}
272
273impl<'p, 'o> Renderer<'p, 'o> {
274 pub fn reset_camera(&mut self) {
276 self.pass.set_bind_group(1, self.camera_bindgroup, &[]);
277 }
278
279 pub fn get_size(&self) -> Vec2<u32> {
281 self.size
282 }
283}