1use std::sync::Arc;
2use image::GenericImageView;
3use wgpu::{BufferUsages, Device, Extent3d, Queue, ShaderModule, StoreOp, Surface, SurfaceConfiguration, TextureDimension};
4use winit::dpi::PhysicalSize;
5use winit::window::Window;
6use crate::{frame::Frame};
7use crate::assets::buffer::Buffer;
8use crate::assets::render::mesh::Mesh;
9use crate::assets::Texture;
10use crate::assets::vertex_layout::GpuVertex;
11use crate::assets_manager::asset_manager::AssetManager;
12use crate::assets_manager::handle::Handle;
13use crate::wgpu::TextureFormat;
14
15pub struct Renderer {
16 pub(crate) device: Device,
17 queue: Queue,
18 surface: Surface<'static>,
19 pub(crate)surface_config: SurfaceConfiguration,
20
21 pub asset_manager: AssetManager,
22
23 pub(crate)depth_texture: Option<wgpu::Texture>,
24 depth_view: Option<wgpu::TextureView>,
25
26 frame: Frame,
27
28 textures_to_clear: Vec<Handle<Texture>>,
29}
30
31impl Renderer {
32 pub async fn new(window: Arc<Window>) -> Self {
33 let instance = wgpu::Instance::default();
34
35 let surface = instance.create_surface(window.clone()).unwrap();
36
37 let adapter = instance.request_adapter(
38 &wgpu::RequestAdapterOptions {
39 compatible_surface: Some(&surface),
40 ..Default::default()
41 },
42 ).await.unwrap();
43
44 let (device, queue) = adapter.request_device(
45 &wgpu::DeviceDescriptor::default(),
46 ).await.unwrap();
47
48 let caps = surface.get_capabilities(&adapter);
49
50 let surface_config = SurfaceConfiguration {
51 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
52 format: caps.formats[0],
53 width: window.inner_size().width,
54 height: window.inner_size().height,
55 present_mode: caps.present_modes[0],
56 alpha_mode: caps.alpha_modes[0],
57 view_formats: vec![],
58 desired_maximum_frame_latency: 2,
59 };
60
61 surface.configure(&device, &surface_config);
62
63 let asset_manager = AssetManager::new();
64
65 let frame = Frame::new();
66
67 Self {
68 device,
69 queue,
70 surface,
71 surface_config,
72 asset_manager,
73 depth_texture: None,
74 depth_view: None,
75 frame,
76 textures_to_clear: vec![],
77 }
78 }
79
80 pub fn render(&mut self) {
81 let output = match self.surface.get_current_texture() {
82 wgpu::CurrentSurfaceTexture::Success(frame) => frame,
83 wgpu::CurrentSurfaceTexture::Suboptimal(frame) => {
84 frame
86 }
87
88 wgpu::CurrentSurfaceTexture::Timeout => {
89 return; }
91 wgpu::CurrentSurfaceTexture::Occluded => {
92 return; }
94 wgpu::CurrentSurfaceTexture::Outdated => {
95 self.surface.configure(&self.device, &self.surface_config);
97 return;
98 }
99 wgpu::CurrentSurfaceTexture::Lost => {
100 self.surface.configure(&self.device, &self.surface_config);
102 return;
103 }
104 wgpu::CurrentSurfaceTexture::Validation => {
105 return;
106 }
107 };
108
109 let view = output
110 .texture
111 .create_view(&wgpu::TextureViewDescriptor::default());
112
113 let mut encoder = self.device.create_command_encoder(
114 &wgpu::CommandEncoderDescriptor {
115 label: Some("Render Encoder"),
116 },
117 );
118
119 for texture in self.textures_to_clear.drain(..){
120 let view = &self.asset_manager.textures.get(texture).unwrap().view;
121
122 let _rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
123 label: Some("Clear Texture Pass"),
124 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
125 view,
126 depth_slice: None,
127 resolve_target: None,
128 ops: wgpu::Operations {
129 load: wgpu::LoadOp::Clear(wgpu::Color {
130 r: 0.0,
131 g: 0.0,
132 b: 0.0,
133 a: 1.0,
134 }),
135 store: Default::default(),
136 },
137 })],
138 depth_stencil_attachment: None,
139 timestamp_writes: None,
140 occlusion_query_set: None,
141 multiview_mask: None,
142 });
143 }
144
145 for compute_task in &self.frame.compute_tasks{
146 compute_task.execute(&mut encoder, &self.asset_manager)
147 }
148
149 {
150 let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
151 label: Some("Render Pass"),
152
153 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
154 view: &view,
155 depth_slice: None,
156 resolve_target: None,
157 ops: wgpu::Operations {
158 load: wgpu::LoadOp::Clear(wgpu::Color {
159 r: 0.0,
160 g: 0.0,
161 b: 0.0,
162 a: 1.0,
163 }),
164 store: wgpu::StoreOp::Store,
165 },
166 })],
167 depth_stencil_attachment: self.depth_view.as_ref().map(|view| wgpu::RenderPassDepthStencilAttachment {
168 view,
169 depth_ops: Some(wgpu::Operations {
170 load: wgpu::LoadOp::Clear(1.0),
171 store: StoreOp::Store,
172 }),
173 stencil_ops: None,
174 }) ,
175 occlusion_query_set: None,
176 timestamp_writes: None,
177 multiview_mask: None,
178 });
179
180 for item in &self.frame.render_tasks {
181 let material = self.asset_manager.materials.get(item.material).unwrap();
182 let pipeline = self.asset_manager.render_pipelines.get(material.pipeline).unwrap();
183 let mesh = self.asset_manager.meshes.get(item.mesh).unwrap();
184
185 render_pass.set_pipeline(&pipeline.pipeline);
186 render_pass.set_bind_group(0, &material.bind_group, &[]);
187 render_pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
188 render_pass.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
189
190 if let Some(instances) = item.instances{
191 let instances = self.asset_manager.buffers.get(instances).unwrap();
192 render_pass.set_vertex_buffer(1, instances.buffer.slice(..));
193 render_pass.draw_indexed(0..mesh.index_count, 0,item.range.clone().unwrap());
194 }
195 else{
196 render_pass.draw_indexed(0..mesh.index_count, 0,0..1);
197 }
198
199
200 }
201 }
202
203 self.queue.submit(Some(encoder.finish()));
204
205 output.present();
206 }
207
208 pub fn resize_surface(&mut self, size: PhysicalSize<u32>) {
209 self.surface_config.width = size.width;
210 self.surface_config.height = size.height;
211 self.surface.configure(&self.device, &self.surface_config);
212 self.create_depth_texture(size.width, size.height);
213 }
214
215 pub fn window_aspect(&self) -> f32 {
216 self.surface_config.width as f32 / self.surface_config.height as f32
217 }
218
219 pub fn width(&self) -> u32{
220 self.surface_config.width
221 }
222 pub fn height(&self) -> u32{
223 self.surface_config.height
224 }
225
226 pub fn begin_frame(&mut self) -> &mut Frame {
227 self.frame.clear();
228 &mut self.frame
229 }
230
231 pub fn current_frame(&mut self) -> &mut Frame {
232 &mut self.frame
233 }
234
235 pub fn create_mesh<T: GpuVertex>(&mut self, vertices: &[T],indices: &[u16]) -> Handle<Mesh>{
236 let mesh = Mesh::new(&self.device,vertices,indices);
237 self.asset_manager.meshes.insert(mesh)
238 }
239
240 pub(crate) fn create_depth_texture(&mut self, width: u32, height: u32){
241 let texture = self.device.create_texture(&wgpu::TextureDescriptor {
242 size: wgpu::Extent3d {
243 width,
244 height,
245 depth_or_array_layers: 1,
246 },
247 mip_level_count: 1,
248 sample_count: 1,
249 dimension: wgpu::TextureDimension::D2,
250 format: wgpu::TextureFormat::Depth24Plus,
251 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
252 label: Some("depth_texture"),
253 view_formats: &[],
254 });
255
256 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
257
258 self.depth_view = Some(view);
259 self.depth_texture = Some(texture);
260 }
261
262
263 pub fn create_buffer(&mut self,buffer_usages: BufferUsages,size:u64) -> Handle<Buffer> {
264 let buffer = Buffer::new(&self.device,size,buffer_usages);
265 self.asset_manager.buffers.insert(buffer)
266 }
267
268 pub fn create_buffer_with_contents(&mut self,buffer_usages: BufferUsages,contents:&[u8]) -> Handle<Buffer> {
269 let buffer = Buffer::from_contents(&self.device,contents,buffer_usages);
270 self.asset_manager.buffers.insert(buffer)
271 }
272
273 pub fn load_shader(&mut self,src: &'static str) -> Handle<ShaderModule>{
274 let shader = self.device.create_shader_module(wgpu::ShaderModuleDescriptor {
275 label: Some("Shader"),
276 source: wgpu::ShaderSource::Wgsl(src.into()),
277 });
278 self.asset_manager.shaders.insert(shader)
279 }
280
281 pub fn write_buffer<T: bytemuck::Pod>(&self,handle: Handle<Buffer>,data: T){
282 let uniform = self.asset_manager.buffers.get(handle).unwrap();
283 self.queue.write_buffer(&uniform.buffer, 0, bytemuck::cast_slice(&[data]));
284 }
285 pub fn load_texture_from_file(&mut self,texture_bytes: Vec<u8>) -> Handle<Texture> {
286 let image = image::load_from_memory(texture_bytes.as_slice()).unwrap();
287 let rgba = image.to_rgba8();
288
289 let dims = image.dimensions();
290
291 let texture_size = wgpu::Extent3d{
292 width: dims.0,
293 height: dims.1,
294 depth_or_array_layers: 1,
295 };
296
297 let texture = self.device.create_texture(&wgpu::TextureDescriptor{
298 label: None,
299 size: texture_size,
300 mip_level_count: 1,
301 sample_count: 1,
302 dimension: TextureDimension::D2,
303 format: TextureFormat::Rgba8UnormSrgb,
304 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
305 view_formats: &[],
306 });
307
308 self.queue.write_texture(
309 wgpu::TexelCopyTextureInfo{
310 texture: &texture,
311 mip_level: 0,
312 origin: wgpu::Origin3d::ZERO,
313 aspect: wgpu::TextureAspect::All,
314 },
315 &rgba,
316 wgpu::TexelCopyBufferLayout{
317 offset: 0,
318 bytes_per_row: Some(4 * dims.0),
319 rows_per_image: Some(dims.1),
320 },
321 texture_size
322 );
323
324 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
325
326 self.asset_manager.textures.insert(Texture::new(texture,view))
327 }
328
329 pub fn write_texture(&self,texture: Handle<Texture>,bytes: &[u8],byte_per_pixel: u32, texture_size: Extent3d){
330 let texture = &self.asset_manager.textures.get(texture).unwrap().texture;
331
332 self.queue.write_texture(
333 wgpu::TexelCopyTextureInfo{
334 texture,
335 mip_level: 0,
336 origin: wgpu::Origin3d::ZERO,
337 aspect: wgpu::TextureAspect::All,
338 },
339 bytes,
340 wgpu::TexelCopyBufferLayout{
341 offset: 0,
342 bytes_per_row: Some(byte_per_pixel * texture_size.width),
343 rows_per_image: Some(texture_size.height),
344 },
345 texture_size
346 );
347 }
348
349 pub fn clear_texture(&mut self, texture: Handle<Texture>){
350 self.textures_to_clear.push(texture);
351 }
352}
353