1use std::sync::Arc;
2use wgpu::{BufferUsages, Device, Queue, ShaderModule, StoreOp, Surface, SurfaceConfiguration};
3use winit::dpi::PhysicalSize;
4use winit::window::Window;
5use crate::{frame::Frame};
6use crate::assets::buffer::Buffer;
7use crate::assets::compute::bind_group::{ComputeBindGroup, ComputeBindGroupBuilder};
8use crate::assets::compute::pipeline::{ComputePipeline, ComputePipelineBuilder};
9use crate::assets::render::material::{Material, MaterialBuilder};
10use crate::assets::render::mesh::Mesh;
11use crate::assets::render::pipeline::{RenderPipeline, RenderPipelineBuilder};
12use crate::assets::vertex_layout::GpuVertex;
13use crate::assets_manager::asset_manager::AssetManager;
14use crate::assets_manager::asset_registry::AssetRegistry;
15use crate::assets_manager::handle::Handle;
16
17pub struct Renderer {
18 device: Device,
19 queue: Queue,
20 surface: Surface<'static>,
21 surface_config: SurfaceConfiguration,
22
23 pub asset_registry: AssetRegistry,
24 pub asset_manager: AssetManager,
25
26 depth_texture: Option<wgpu::Texture>,
27 depth_view: Option<wgpu::TextureView>,
28
29 frame: Frame,
30}
31
32impl Renderer {
33 pub async fn new(window: Arc<Window>) -> Self {
34 let instance = wgpu::Instance::default();
35
36 let surface = instance.create_surface(window.clone()).unwrap();
37
38 let adapter = instance.request_adapter(
39 &wgpu::RequestAdapterOptions {
40 compatible_surface: Some(&surface),
41 ..Default::default()
42 },
43 ).await.unwrap();
44
45 let (device, queue) = adapter.request_device(
46 &wgpu::DeviceDescriptor::default(),
47 ).await.unwrap();
48
49 let caps = surface.get_capabilities(&adapter);
50
51 let surface_config = SurfaceConfiguration {
52 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
53 format: caps.formats[0],
54 width: window.inner_size().width,
55 height: window.inner_size().height,
56 present_mode: caps.present_modes[0],
57 alpha_mode: caps.alpha_modes[0],
58 view_formats: vec![],
59 desired_maximum_frame_latency: 2,
60 };
61
62 surface.configure(&device, &surface_config);
63
64 let asset_manager = AssetManager::new();
65 let asset_registry = AssetRegistry::new();
66
67 let frame = Frame::new();
68
69 Self {
70 device,
71 queue,
72 surface,
73 surface_config,
74 asset_registry,
75 asset_manager,
76 depth_texture: None,
77 depth_view: None,
78 frame,
79 }
80 }
81
82 pub fn render(&self) {
83 let output = match self.surface.get_current_texture() {
84 wgpu::CurrentSurfaceTexture::Success(frame) => frame,
85 wgpu::CurrentSurfaceTexture::Suboptimal(frame) => {
86 frame
88 }
89
90 wgpu::CurrentSurfaceTexture::Timeout => {
91 return; }
93 wgpu::CurrentSurfaceTexture::Occluded => {
94 return; }
96 wgpu::CurrentSurfaceTexture::Outdated => {
97 self.surface.configure(&self.device, &self.surface_config);
99 return;
100 }
101 wgpu::CurrentSurfaceTexture::Lost => {
102 self.surface.configure(&self.device, &self.surface_config);
104 return;
105 }
106 wgpu::CurrentSurfaceTexture::Validation => {
107 return;
108 }
109 };
110
111 let view = output
112 .texture
113 .create_view(&wgpu::TextureViewDescriptor::default());
114
115 let mut encoder = self.device.create_command_encoder(
116 &wgpu::CommandEncoderDescriptor {
117 label: Some("Render Encoder"),
118 },
119 );
120
121 for compute_task in &self.frame.compute_tasks{
122 compute_task.execute(&mut encoder, &self.asset_manager)
123 }
124
125 {
126 let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
127 label: Some("Render Pass"),
128
129 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
130 view: &view,
131 depth_slice: None,
132 resolve_target: None,
133 ops: wgpu::Operations {
134 load: wgpu::LoadOp::Clear(wgpu::Color {
135 r: 0.0,
136 g: 0.0,
137 b: 0.0,
138 a: 1.0,
139 }),
140 store: wgpu::StoreOp::Store,
141 },
142 })],
143 depth_stencil_attachment: match &self.depth_view{
144 Some(view) => {
145 Some(wgpu::RenderPassDepthStencilAttachment {
146 view,
147 depth_ops: Some(wgpu::Operations {
148 load: wgpu::LoadOp::Clear(1.0),
149 store: StoreOp::Store,
150 }),
151 stencil_ops: None,
152 })
153 }
154 None => None
155 } ,
156 occlusion_query_set: None,
157 timestamp_writes: None,
158 multiview_mask: None,
159 });
160
161 for item in &self.frame.render_tasks {
162 let material = self.asset_manager.materials.get(item.material).unwrap();
163 let pipeline = self.asset_manager.render_pipelines.get(material.pipeline).unwrap();
164 let mesh = self.asset_manager.meshes.get(item.mesh).unwrap();
165 let instances = self.asset_manager.buffers.get(item.instances).unwrap();
166
167 render_pass.set_pipeline(&pipeline.pipeline);
168 render_pass.set_bind_group(0, &material.bind_group, &[]);
169 render_pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
170 render_pass.set_vertex_buffer(1, instances.buffer.slice(..));
171 render_pass.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
172
173 render_pass.draw_indexed(0..mesh.index_count, 0,item.range.clone());
174 }
175 }
176
177 self.queue.submit(Some(encoder.finish()));
178
179 output.present();
180 }
181
182 pub fn resize_surface(&mut self, size: PhysicalSize<u32>) {
183 self.surface_config.width = size.width;
184 self.surface_config.height = size.height;
185 self.surface.configure(&self.device, &self.surface_config);
186 self.create_depth_texture(size.width, size.height);
187 }
188
189 pub fn window_aspect(&self) -> f32 {
190 self.surface_config.width as f32 / self.surface_config.height as f32
191 }
192
193 pub fn begin_frame(&mut self) -> &mut Frame {
194 self.frame.clear();
195 &mut self.frame
196 }
197
198 pub fn current_frame(&mut self) -> &mut Frame {
199 &mut self.frame
200 }
201
202 pub fn create_mesh<T: GpuVertex>(&mut self, vertices: &[T],indices: &[u32]) -> Handle<Mesh>{
203 let mesh = Mesh::new(&self.device,vertices,indices);
204 self.asset_manager.meshes.insert(mesh)
205 }
206
207 pub fn create_render_pipeline(&mut self, builder: RenderPipelineBuilder) -> Handle<RenderPipeline> {
208 if builder.depth_format.is_some() && self.depth_texture.is_none() {
209 self.create_depth_texture(self.surface_config.width,self.surface_config.height);
210 }
211
212 let pipeline = builder.build(&self.device,&self.asset_manager,&self.surface_config);
213 self.asset_manager.render_pipelines.insert(pipeline)
214 }
215
216 fn create_depth_texture(&mut self, width: u32, height: u32){
217 let texture = self.device.create_texture(&wgpu::TextureDescriptor {
218 size: wgpu::Extent3d {
219 width,
220 height,
221 depth_or_array_layers: 1,
222 },
223 mip_level_count: 1,
224 sample_count: 1,
225 dimension: wgpu::TextureDimension::D2,
226 format: wgpu::TextureFormat::Depth24Plus,
227 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
228 label: Some("depth_texture"),
229 view_formats: &[],
230 });
231
232 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
233
234 self.depth_view = Some(view);
235 self.depth_texture = Some(texture);
236 }
237
238 pub fn create_material(&mut self,builder: MaterialBuilder) -> Handle<Material> {
239 let material = builder.build(&self.device,&self.asset_manager);
240 self.asset_manager.materials.insert(material)
241 }
242
243 pub fn create_buffer(&mut self,buffer_usages: BufferUsages,size:u64) -> Handle<Buffer> {
244 let buffer = Buffer::new(&self.device,size,buffer_usages);
245 self.asset_manager.buffers.insert(buffer)
246 }
247
248 pub fn create_buffer_with_contents(&mut self,buffer_usages: BufferUsages,contents:&[u8]) -> Handle<Buffer> {
249 let buffer = Buffer::from_contents(&self.device,contents,buffer_usages);
250 self.asset_manager.buffers.insert(buffer)
251 }
252
253 pub fn load_shader(&mut self,src: &'static str) -> Handle<ShaderModule>{
254 let shader = self.device.create_shader_module(wgpu::ShaderModuleDescriptor {
255 label: Some("Shader"),
256 source: wgpu::ShaderSource::Wgsl(src.into()),
257 });
258 self.asset_manager.shaders.insert(shader)
259 }
260
261 pub fn write_buffer<T: bytemuck::Pod>(&self,handle: Handle<Buffer>,data: T){
262 let uniform = self.asset_manager.buffers.get(handle).unwrap();
263 self.queue.write_buffer(&uniform.buffer, 0, bytemuck::cast_slice(&[data]));
264 }
265
266 pub fn create_compute_pipeline(&mut self,builder: ComputePipelineBuilder) -> Handle<ComputePipeline>{
267 let pipeline = builder.build(&self.device,&self.asset_manager);
268 self.asset_manager.compute_pipelines.insert(pipeline)
269 }
270
271 pub fn create_compute_bind_group(&mut self, builder: ComputeBindGroupBuilder) -> Handle<ComputeBindGroup>{
272 let bind_group = builder.build(&self.device,&self.asset_manager);
273 self.asset_manager.compute_bind_groups.insert(bind_group)
274 }
275
276}
277