1use std::sync::Arc;
2use image::GenericImageView;
3use wgpu::{BufferUsages, Device, 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::asset_registry::AssetRegistry;
13use crate::assets_manager::handle::Handle;
14use crate::wgpu::TextureFormat;
15
16pub struct Renderer {
17 pub(crate) device: Device,
18 queue: Queue,
19 surface: Surface<'static>,
20 pub(crate)surface_config: SurfaceConfiguration,
21
22 pub asset_registry: AssetRegistry,
23 pub asset_manager: AssetManager,
24
25 pub(crate)depth_texture: Option<wgpu::Texture>,
26 depth_view: Option<wgpu::TextureView>,
27
28 frame: Frame,
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 let asset_registry = AssetRegistry::new();
65
66 let frame = Frame::new();
67
68 Self {
69 device,
70 queue,
71 surface,
72 surface_config,
73 asset_registry,
74 asset_manager,
75 depth_texture: None,
76 depth_view: None,
77 frame,
78 }
79 }
80
81 pub fn render(&self) {
82 let output = match self.surface.get_current_texture() {
83 wgpu::CurrentSurfaceTexture::Success(frame) => frame,
84 wgpu::CurrentSurfaceTexture::Suboptimal(frame) => {
85 frame
87 }
88
89 wgpu::CurrentSurfaceTexture::Timeout => {
90 return; }
92 wgpu::CurrentSurfaceTexture::Occluded => {
93 return; }
95 wgpu::CurrentSurfaceTexture::Outdated => {
96 self.surface.configure(&self.device, &self.surface_config);
98 return;
99 }
100 wgpu::CurrentSurfaceTexture::Lost => {
101 self.surface.configure(&self.device, &self.surface_config);
103 return;
104 }
105 wgpu::CurrentSurfaceTexture::Validation => {
106 return;
107 }
108 };
109
110 let view = output
111 .texture
112 .create_view(&wgpu::TextureViewDescriptor::default());
113
114 let mut encoder = self.device.create_command_encoder(
115 &wgpu::CommandEncoderDescriptor {
116 label: Some("Render Encoder"),
117 },
118 );
119
120 for compute_task in &self.frame.compute_tasks{
121 compute_task.execute(&mut encoder, &self.asset_manager)
122 }
123
124 {
125 let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
126 label: Some("Render Pass"),
127
128 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
129 view: &view,
130 depth_slice: None,
131 resolve_target: None,
132 ops: wgpu::Operations {
133 load: wgpu::LoadOp::Clear(wgpu::Color {
134 r: 0.0,
135 g: 0.0,
136 b: 0.0,
137 a: 1.0,
138 }),
139 store: wgpu::StoreOp::Store,
140 },
141 })],
142 depth_stencil_attachment: self.depth_view.as_ref().map(|view| wgpu::RenderPassDepthStencilAttachment {
143 view,
144 depth_ops: Some(wgpu::Operations {
145 load: wgpu::LoadOp::Clear(1.0),
146 store: StoreOp::Store,
147 }),
148 stencil_ops: None,
149 }) ,
150 occlusion_query_set: None,
151 timestamp_writes: None,
152 multiview_mask: None,
153 });
154
155 for item in &self.frame.render_tasks {
156 let material = self.asset_manager.materials.get(item.material).unwrap();
157 let pipeline = self.asset_manager.render_pipelines.get(material.pipeline).unwrap();
158 let mesh = self.asset_manager.meshes.get(item.mesh).unwrap();
159
160 render_pass.set_pipeline(&pipeline.pipeline);
161 render_pass.set_bind_group(0, &material.bind_group, &[]);
162 render_pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
163 render_pass.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
164
165 if let Some(instances) = item.instances{
166 let instances = self.asset_manager.buffers.get(instances).unwrap();
167 render_pass.set_vertex_buffer(1, instances.buffer.slice(..));
168 render_pass.draw_indexed(0..mesh.index_count, 0,item.range.clone().unwrap());
169 }
170 else{
171 render_pass.draw_indexed(0..mesh.index_count, 0,0..1);
172 }
173
174
175 }
176 }
177
178 self.queue.submit(Some(encoder.finish()));
179
180 output.present();
181 }
182
183 pub fn resize_surface(&mut self, size: PhysicalSize<u32>) {
184 self.surface_config.width = size.width;
185 self.surface_config.height = size.height;
186 self.surface.configure(&self.device, &self.surface_config);
187 self.create_depth_texture(size.width, size.height);
188 }
189
190 pub fn window_aspect(&self) -> f32 {
191 self.surface_config.width as f32 / self.surface_config.height as f32
192 }
193
194 pub fn width(&self) -> u32{
195 self.surface_config.width
196 }
197 pub fn height(&self) -> u32{
198 self.surface_config.height
199 }
200
201 pub fn begin_frame(&mut self) -> &mut Frame {
202 self.frame.clear();
203 &mut self.frame
204 }
205
206 pub fn current_frame(&mut self) -> &mut Frame {
207 &mut self.frame
208 }
209
210 pub fn create_mesh<T: GpuVertex>(&mut self, vertices: &[T],indices: &[u16]) -> Handle<Mesh>{
211 let mesh = Mesh::new(&self.device,vertices,indices);
212 self.asset_manager.meshes.insert(mesh)
213 }
214
215 pub(crate) fn create_depth_texture(&mut self, width: u32, height: u32){
216 let texture = self.device.create_texture(&wgpu::TextureDescriptor {
217 size: wgpu::Extent3d {
218 width,
219 height,
220 depth_or_array_layers: 1,
221 },
222 mip_level_count: 1,
223 sample_count: 1,
224 dimension: wgpu::TextureDimension::D2,
225 format: wgpu::TextureFormat::Depth24Plus,
226 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
227 label: Some("depth_texture"),
228 view_formats: &[],
229 });
230
231 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
232
233 self.depth_view = Some(view);
234 self.depth_texture = Some(texture);
235 }
236
237
238 pub fn create_buffer(&mut self,buffer_usages: BufferUsages,size:u64) -> Handle<Buffer> {
239 let buffer = Buffer::new(&self.device,size,buffer_usages);
240 self.asset_manager.buffers.insert(buffer)
241 }
242
243 pub fn create_buffer_with_contents(&mut self,buffer_usages: BufferUsages,contents:&[u8]) -> Handle<Buffer> {
244 let buffer = Buffer::from_contents(&self.device,contents,buffer_usages);
245 self.asset_manager.buffers.insert(buffer)
246 }
247
248 pub fn load_shader(&mut self,src: &'static str) -> Handle<ShaderModule>{
249 let shader = self.device.create_shader_module(wgpu::ShaderModuleDescriptor {
250 label: Some("Shader"),
251 source: wgpu::ShaderSource::Wgsl(src.into()),
252 });
253 self.asset_manager.shaders.insert(shader)
254 }
255
256 pub fn write_buffer<T: bytemuck::Pod>(&self,handle: Handle<Buffer>,data: T){
257 let uniform = self.asset_manager.buffers.get(handle).unwrap();
258 self.queue.write_buffer(&uniform.buffer, 0, bytemuck::cast_slice(&[data]));
259 }
260 pub fn load_texture_from_file(&mut self,texture_bytes: Vec<u8>) -> Handle<Texture> {
261 let image = image::load_from_memory(texture_bytes.as_slice()).unwrap();
262 let rgba = image.to_rgba8();
263
264 let dims = image.dimensions();
265
266 let texture_size = wgpu::Extent3d{
267 width: dims.0,
268 height: dims.1,
269 depth_or_array_layers: 1,
270 };
271
272 let texture = self.device.create_texture(&wgpu::TextureDescriptor{
273 label: None,
274 size: texture_size,
275 mip_level_count: 1,
276 sample_count: 1,
277 dimension: TextureDimension::D2,
278 format: TextureFormat::Rgba8UnormSrgb,
279 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
280 view_formats: &[],
281 });
282
283 self.queue.write_texture(
284 wgpu::TexelCopyTextureInfo{
285 texture: &texture,
286 mip_level: 0,
287 origin: wgpu::Origin3d::ZERO,
288 aspect: wgpu::TextureAspect::All,
289 },
290 &rgba,
291 wgpu::TexelCopyBufferLayout{
292 offset: 0,
293 bytes_per_row: Some(4 * dims.0),
294 rows_per_image: Some(dims.1),
295 },
296 texture_size
297 );
298
299 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
300
301 self.asset_manager.textures.insert(Texture::new(texture,view))
302 }
303}
304