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