From c2776e1bc45d174b67f6d91d7767bdbd1772eb61 Mon Sep 17 00:00:00 2001 From: lisk77 Date: Mon, 27 Oct 2025 17:34:03 +0100 Subject: [PATCH] feat(renderer): added RenderResources and Batches and filled out the Renderer trait for Renderer2D --- .../src/{draw_info.rs => batch.rs} | 101 ++--- crates/comet_renderer/src/lib.rs | 5 +- crates/comet_renderer/src/render_context.rs | 27 +- crates/comet_renderer/src/render_group.rs | 4 - crates/comet_renderer/src/render_pass.rs | 349 +----------------- crates/comet_renderer/src/render_resources.rs | 66 ++++ crates/comet_renderer/src/renderer2d.rs | 36 +- 7 files changed, 198 insertions(+), 390 deletions(-) rename crates/comet_renderer/src/{draw_info.rs => batch.rs} (64%) delete mode 100644 crates/comet_renderer/src/render_group.rs create mode 100644 crates/comet_renderer/src/render_resources.rs diff --git a/crates/comet_renderer/src/draw_info.rs b/crates/comet_renderer/src/batch.rs similarity index 64% rename from crates/comet_renderer/src/draw_info.rs rename to crates/comet_renderer/src/batch.rs index f4f2cd4..4866c18 100644 --- a/crates/comet_renderer/src/draw_info.rs +++ b/crates/comet_renderer/src/batch.rs @@ -1,10 +1,9 @@ -use wgpu::{BindGroupLayout, BufferUsages, Device}; -use wgpu::util::DeviceExt; use comet_resources::{Texture, Vertex}; -use comet_log::*; +use wgpu::util::DeviceExt; +use wgpu::{BindGroupLayout, BufferUsages, Device}; -pub struct DrawInfo { - name: String, +pub struct Batch { + label: String, texture: wgpu::BindGroup, vertex_data: Vec, index_data: Vec, @@ -13,15 +12,15 @@ pub struct DrawInfo { num_indices: u32, } -impl DrawInfo { +impl Batch { pub fn new( - name: String, + label: String, device: &Device, texture: &Texture, texture_bind_group_layout: &BindGroupLayout, texture_sampler: &wgpu::Sampler, vertex_data: Vec, - index_data: Vec + index_data: Vec, ) -> Self { let texture_bind = device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &texture_bind_group_layout, @@ -35,75 +34,81 @@ impl DrawInfo { resource: wgpu::BindingResource::Sampler(&texture_sampler), }, ], - label: Some(format!("{} Texture", name).as_str()), + label: Some(format!("{} Texture", label).as_str()), }); let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Vertex Buffer", &name).as_str()), + label: Some(format!("{} Vertex Buffer", &label).as_str()), contents: bytemuck::cast_slice(&vertex_data), usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, }); let num_indices = index_data.len() as u32; - + let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Index Buffer", &name).as_str()), + label: Some(format!("{} Index Buffer", &label).as_str()), contents: bytemuck::cast_slice(&index_data), usage: BufferUsages::INDEX | BufferUsages::COPY_DST, }); Self { - name, + label, texture: texture_bind, vertex_data, index_data, vertex_buffer, index_buffer, - num_indices + num_indices, } } - - pub fn name(&self) -> &String { - &self.name - } - + pub fn texture(&self) -> &wgpu::BindGroup { &self.texture } - + pub fn vertex_buffer(&self) -> &wgpu::Buffer { &self.vertex_buffer } - + pub fn vertex_data(&self) -> &Vec { &self.vertex_data } - + pub fn index_buffer(&self) -> &wgpu::Buffer { &self.index_buffer } - + pub fn index_data(&self) -> &Vec { &self.index_data } - + pub fn num_indices(&self) -> u32 { self.num_indices } - - pub fn update_vertex_buffer(&mut self, device: &Device, queue: &wgpu::Queue, vertex_data: Vec) { + + pub fn update_vertex_buffer( + &mut self, + device: &Device, + queue: &wgpu::Queue, + vertex_data: Vec, + ) { let new_vertex_size = vertex_data.len() as u64 * size_of::() as u64; match vertex_data == self.vertex_data { - true => {}, + true => {} false => { match new_vertex_size > self.vertex_buffer.size() { - false => queue.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&vertex_data)), + false => queue.write_buffer( + &self.vertex_buffer, + 0, + bytemuck::cast_slice(&vertex_data), + ), true => { - self.vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Vertex Buffer", self.name).as_str()), - contents: bytemuck::cast_slice(&vertex_data), - usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, - }); + self.vertex_buffer = + device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some(format!("{} Vertex Buffer", self.label).as_str()), + contents: bytemuck::cast_slice(&vertex_data), + usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, + }); } } self.vertex_data = vertex_data; @@ -111,19 +116,27 @@ impl DrawInfo { } } - pub fn update_index_buffer(&mut self, device: &Device, queue: &wgpu::Queue, index_data: Vec) { + pub fn update_index_buffer( + &mut self, + device: &Device, + queue: &wgpu::Queue, + index_data: Vec, + ) { let new_index_size = index_data.len() as u64 * size_of::() as u64; match index_data == self.index_data { - true => {}, + true => {} false => { match new_index_size > self.index_buffer.size() { - false => queue.write_buffer(&self.index_buffer, 0, bytemuck::cast_slice(&index_data)), + false => { + queue.write_buffer(&self.index_buffer, 0, bytemuck::cast_slice(&index_data)) + } true => { - self.index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Index Buffer", self.name).as_str()), - contents: bytemuck::cast_slice(&index_data), - usage: BufferUsages::INDEX | BufferUsages::COPY_DST, - }); + self.index_buffer = + device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some(format!("{} Index Buffer", self.label).as_str()), + contents: bytemuck::cast_slice(&index_data), + usage: BufferUsages::INDEX | BufferUsages::COPY_DST, + }); } } self.num_indices = index_data.len() as u32; @@ -131,7 +144,7 @@ impl DrawInfo { } } } - + pub fn set_texture(&mut self, device: &Device, layout: &BindGroupLayout, texture: &Texture) { self.texture = device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &layout, @@ -145,7 +158,7 @@ impl DrawInfo { resource: wgpu::BindingResource::Sampler(&texture.sampler), }, ], - label: Some(format!("{} Texture Bind Group", self.name).as_str()), + label: Some(format!("{} Texture Bind Group", self.label).as_str()), }); } -} \ No newline at end of file +} diff --git a/crates/comet_renderer/src/lib.rs b/crates/comet_renderer/src/lib.rs index 44e7918..f193269 100644 --- a/crates/comet_renderer/src/lib.rs +++ b/crates/comet_renderer/src/lib.rs @@ -1,6 +1,7 @@ +mod batch; mod camera; -mod draw_info; pub mod render_context; -mod render_group; +mod render_pass; +pub mod render_resources; pub mod renderer; pub mod renderer2d; diff --git a/crates/comet_renderer/src/render_context.rs b/crates/comet_renderer/src/render_context.rs index 6ba7e9f..c283b74 100644 --- a/crates/comet_renderer/src/render_context.rs +++ b/crates/comet_renderer/src/render_context.rs @@ -1,5 +1,6 @@ +use crate::{batch::Batch, render_resources::RenderResources}; use comet_colors::Color; -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use winit::{dpi::PhysicalSize, window::Window}; pub struct RenderContext<'a> { @@ -10,6 +11,9 @@ pub struct RenderContext<'a> { size: PhysicalSize, scale_factor: f64, clear_color: wgpu::Color, + render_pipelines: HashMap, + batches: HashMap, + resources: RenderResources, } impl<'a> RenderContext<'a> { @@ -37,7 +41,7 @@ impl<'a> RenderContext<'a> { required_limits: wgpu::Limits::default(), memory_hints: Default::default(), }, - None, // Trace path + None, )) .unwrap(); @@ -77,6 +81,9 @@ impl<'a> RenderContext<'a> { size, scale_factor, clear_color, + render_pipelines: HashMap::new(), + batches: HashMap::new(), + resources: RenderResources::new(), } } @@ -123,4 +130,20 @@ impl<'a> RenderContext<'a> { pub fn clear_color(&self) -> wgpu::Color { self.clear_color } + + pub fn get_pipeline(&self, label: String) -> Option<&wgpu::RenderPipeline> { + self.render_pipelines.get(&label) + } + + pub fn get_batch(&self, label: String) -> Option<&Batch> { + self.batches.get(&label) + } + + pub fn resources(&self) -> &RenderResources { + &self.resources + } + + pub fn resources_mut(&mut self) -> &mut RenderResources { + &mut self.resources + } } diff --git a/crates/comet_renderer/src/render_group.rs b/crates/comet_renderer/src/render_group.rs deleted file mode 100644 index a9e795d..0000000 --- a/crates/comet_renderer/src/render_group.rs +++ /dev/null @@ -1,4 +0,0 @@ - pub struct RenderGroup { - pipeline: wgpu::RenderPipeline, - entities: Vec - } \ No newline at end of file diff --git a/crates/comet_renderer/src/render_pass.rs b/crates/comet_renderer/src/render_pass.rs index fb81041..5dd9799 100644 --- a/crates/comet_renderer/src/render_pass.rs +++ b/crates/comet_renderer/src/render_pass.rs @@ -1,338 +1,19 @@ -use wgpu::{ShaderModule, BindGroup, BindGroupLayout, BufferUsages, Device, Queue, RenderPipeline, PipelineLayout, SurfaceConfiguration, TextureFormat}; -use wgpu::util::DeviceExt; -use comet_resources::{Vertex, Texture}; +use crate::render_context::RenderContext; -#[derive(Debug, Clone)] -pub enum RenderPassType { - Engine, - User +pub struct RenderPass { + pub name: String, + pub execute: Box< + dyn Fn(&mut RenderContext, &mut wgpu::CommandEncoder, &wgpu::TextureView) + Send + Sync, + >, } - -pub struct RenderPassInfo { - pass_name: String, - pass_type: RenderPassType, - texture_bind_group: BindGroup, - vertex_buffer: wgpu::Buffer, - index_buffer: wgpu::Buffer, - vertex_data: Vec, - index_data: Vec, - num_indices: u32, - pipeline: Option +impl RenderPass { + pub fn new( + name: String, + execute: Box< + dyn Fn(&mut RenderContext, &mut wgpu::CommandEncoder, &wgpu::TextureView) + Send + Sync, + >, + ) -> Self { + Self { name, execute } + } } - -impl RenderPassInfo { - pub fn new_user_pass( - device: &Device, - pass_name: String, - texture_group_layout: &BindGroupLayout, - texture: &Texture, - shader: &ShaderModule, - vertex_data: Vec, - index_data: Vec, - pipeline_layout: &PipelineLayout, - config: &SurfaceConfiguration - ) -> Self { - let num_indices = index_data.len() as u32; - let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Vertex Buffer", pass_name).as_str()), - contents: bytemuck::cast_slice(&vertex_data), - usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, - }); - - let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Index Buffer", pass_name).as_str()), - contents: bytemuck::cast_slice(&index_data), - usage: BufferUsages::INDEX | BufferUsages::COPY_DST, - }); - - let texture_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &texture_group_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&texture.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&texture.sampler), - }, - ], - label: Some(format!("{} Texture Bind Group", pass_name).as_str()), - }); - - let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Render Pipeline"), - layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: "vs_main", - buffers: &[Vertex::desc()], - compilation_options: Default::default(), - }, - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: "fs_main", - targets: &[Some(wgpu::ColorTargetState { - format: config.format, - blend: Some(wgpu::BlendState { - color: wgpu::BlendComponent { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha: wgpu::BlendComponent { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - }), - write_mask: wgpu::ColorWrites::ALL, - })], - compilation_options: Default::default(), - }), - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: Some(wgpu::Face::Back), - polygon_mode: wgpu::PolygonMode::Fill, - unclipped_depth: false, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - multiview: None, - cache: None, - }); - - Self { - pass_name, - pass_type: RenderPassType::User, - texture_bind_group, - vertex_buffer, - index_buffer, - vertex_data, - index_data, - num_indices, - pipeline: Some(pipeline) - } - } - - pub fn new_engine_pass( - device: &Device, - pass_name: String, - texture_group_layout: &BindGroupLayout, - texture: &Texture, - vertex_data: Vec, - index_data: Vec, - ) -> Self { - let num_indices = index_data.len() as u32; - let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Vertex Buffer", pass_name).as_str()), - contents: bytemuck::cast_slice(&vertex_data), - usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, - }); - - let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Index Buffer", pass_name).as_str()), - contents: bytemuck::cast_slice(&index_data), - usage: BufferUsages::INDEX | BufferUsages::COPY_DST, - }); - - let texture_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &texture_group_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&texture.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&texture.sampler), - }, - ], - label: Some(format!("{} Texture Bind Group", pass_name).as_str()), - }); - Self { - pass_name, - pass_type: RenderPassType::Engine, - texture_bind_group, - vertex_buffer, - index_buffer, - vertex_data, - index_data, - num_indices, - pipeline: None - } - } - - pub fn pass_name(&self) -> &str { - &self.pass_name - } - - pub fn pass_type(&self) -> RenderPassType { - self.pass_type.clone() - } - - pub fn set_shader(&mut self, device: &Device, config: &SurfaceConfiguration, pipeline_layout: &PipelineLayout, shader: &ShaderModule) { - self.pipeline = Some(device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Render Pipeline"), - layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: "vs_main", - buffers: &[Vertex::desc()], - compilation_options: Default::default(), - }, - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: "fs_main", - targets: &[Some(wgpu::ColorTargetState { - format: config.format, - blend: Some(wgpu::BlendState { - color: wgpu::BlendComponent { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha: wgpu::BlendComponent { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - }), - write_mask: wgpu::ColorWrites::ALL, - })], - compilation_options: Default::default(), - }), - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: Some(wgpu::Face::Back), - polygon_mode: wgpu::PolygonMode::Fill, - unclipped_depth: false, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - multiview: None, - cache: None, - })); - } - - pub fn texture_bind_group(&self) -> &BindGroup { - &self.texture_bind_group - } - - pub fn set_texture(&mut self, device: &Device, layout: &BindGroupLayout, texture: &Texture) { - self.texture_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&texture.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&texture.sampler), - }, - ], - label: Some(format!("{} Texture Bind Group", self.pass_name).as_str()), - }); - } - - pub fn vertex_buffer(&self) -> &wgpu::Buffer { - &self.vertex_buffer - } - - pub fn vertex_data(&self) -> &Vec { - &self.vertex_data - } - - pub fn set_vertex_buffer(&mut self, device: &Device, queue: &Queue, vertex_data: Vec) { - let new_vertex_size = vertex_data.len() as u64 * size_of::() as u64; - match vertex_data == self.vertex_data { - true => {}, - false => { - match new_vertex_size > self.vertex_buffer.size() { - false => queue.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&vertex_data)), - true => { - self.vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Vertex Buffer", self.pass_name).as_str()), - contents: bytemuck::cast_slice(&vertex_data), - usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, - }); - } - } - self.vertex_data = vertex_data; - } - } - } - - pub fn push_to_vertex_buffer(&mut self, device: &Device, vertex_data: &mut Vec) { - self.vertex_data.append(vertex_data); - self.vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Vertex Buffer", self.pass_name).as_str()), - contents: bytemuck::cast_slice(&vertex_data), - usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, - }); - } - - pub fn index_buffer(&self) -> &wgpu::Buffer { - &self.index_buffer - } - - pub fn index_data(&self) -> &Vec { - &self.index_data - } - - pub fn num_indices(&self) -> u32 { - self.num_indices - } - - pub fn set_index_buffer(&mut self, device: &Device, queue: &Queue, index_data: Vec) { - let new_index_size = index_data.len() as u64 * size_of::() as u64; - match index_data == self.index_data { - true => {}, - false => { - match new_index_size > self.index_buffer.size() { - false => queue.write_buffer(&self.index_buffer, 0, bytemuck::cast_slice(&index_data)), - true => { - self.index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Index Buffer", self.pass_name).as_str()), - contents: bytemuck::cast_slice(&index_data), - usage: BufferUsages::INDEX | BufferUsages::COPY_DST, - }); - } - } - self.num_indices = index_data.len() as u32; - self.index_data = index_data - } - } - } - - pub fn push_to_index_buffer(&mut self, device: &Device, index_data: &mut Vec) { - self.index_data.append(index_data); - self.index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some(format!("{} Index Buffer", self.pass_name).as_str()), - contents: bytemuck::cast_slice(&index_data), - usage: BufferUsages::INDEX | BufferUsages::COPY_DST, - }); - - self.num_indices = self.index_data.len() as u32; - } - - pub fn pipeline(&self) -> Option<&RenderPipeline> { - self.pipeline.as_ref() - } -} \ No newline at end of file diff --git a/crates/comet_renderer/src/render_resources.rs b/crates/comet_renderer/src/render_resources.rs new file mode 100644 index 0000000..24a3a3f --- /dev/null +++ b/crates/comet_renderer/src/render_resources.rs @@ -0,0 +1,66 @@ +use std::collections::HashMap; + +pub struct RenderResources { + bind_groups: HashMap>, + bind_group_layouts: HashMap>, + buffers: HashMap>, + samplers: HashMap, +} + +impl RenderResources { + pub fn new() -> Self { + Self { + bind_groups: HashMap::new(), + bind_group_layouts: HashMap::new(), + buffers: HashMap::new(), + samplers: HashMap::new(), + } + } + + pub fn get_bindgroups(&self, label: String) -> Option<&Vec> { + self.bind_groups.get(&label) + } + + pub fn insert_bindgroup(&mut self, label: String, bind_group: wgpu::BindGroup) { + match self.bind_groups.get_mut(&label) { + None => { + self.bind_groups.insert(label, vec![bind_group]); + } + Some(v) => v.push(bind_group), + }; + } + + pub fn get_bind_group_layout(&self, label: String) -> Option<&Vec> { + self.bind_group_layouts.get(&label) + } + + pub fn insert_bind_group_layout(&mut self, label: String, layout: wgpu::BindGroupLayout) { + match self.bind_group_layouts.get_mut(&label) { + None => { + self.bind_group_layouts.insert(label, vec![layout]); + } + Some(v) => v.push(layout), + } + } + + pub fn get_buffer(&self, label: String) -> Option<&Vec> { + self.buffers.get(&label) + } + + pub fn insert_buffer(&mut self, label: String, buffer: wgpu::Buffer) { + match self.buffers.get_mut(&label) { + None => { + self.buffers.insert(label, vec![buffer]); + } + Some(v) => v.push(buffer), + } + } + + pub fn get_sampler(&self, label: String) -> Option<&wgpu::Sampler> { + self.samplers.get(&label) + } + + pub fn insert_sampler(&mut self, label: String, sampler: wgpu::Sampler) { + self.samplers.insert(label, sampler); + } +} diff --git a/crates/comet_renderer/src/renderer2d.rs b/crates/comet_renderer/src/renderer2d.rs index f95cc4f..39bfbe2 100644 --- a/crates/comet_renderer/src/renderer2d.rs +++ b/crates/comet_renderer/src/renderer2d.rs @@ -1,5 +1,5 @@ use crate::renderer::Renderer; -use crate::{camera::CameraManager, render_context::RenderContext}; +use crate::{camera::CameraManager, render_context::RenderContext, render_pass::RenderPass}; use comet_colors::Color; use comet_resources::graphic_resource_manager::GraphicResourceManager; use std::sync::Arc; @@ -9,6 +9,8 @@ pub struct Renderer2D<'a> { render_context: RenderContext<'a>, resource_manager: GraphicResourceManager, camera_manager: CameraManager, + render_passes: Vec, + last_frame_time: std::time::Instant, delta_time: f32, } @@ -18,6 +20,8 @@ impl<'a> Renderer for Renderer2D<'a> { render_context: RenderContext::new(window, clear_color), resource_manager: GraphicResourceManager::new(), camera_manager: CameraManager::new(), + render_passes: Vec::new(), + last_frame_time: std::time::Instant::now(), delta_time: 0.0, } } @@ -44,11 +48,35 @@ impl<'a> Renderer for Renderer2D<'a> { } fn update(&mut self) -> f32 { - todo!() + let now = std::time::Instant::now(); + self.delta_time = now.duration_since(self.last_frame_time).as_secs_f32(); + self.last_frame_time = now; + self.delta_time } fn render(&mut self) -> Result<(), wgpu::SurfaceError> { - todo!() + let output = self.render_context.surface().get_current_texture()?; + let output_view = output + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + + let mut encoder = + self.render_context + .device() + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Render Encoder"), + }); + + for pass in &self.render_passes { + (pass.execute)(&mut self.render_context, &mut encoder, &output_view); + } + + self.render_context + .queue() + .submit(std::iter::once(encoder.finish())); + + output.present(); + + Ok(()) } } -