From 6182a4b9c8e1e5bee103bba2cccacba6c7eab73c Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sat, 15 Jun 2024 23:52:46 -0400 Subject: [PATCH] render: simplify light buffer updating --- examples/testbed/testbed-renderdoc.cap | 6 +- lyra-game/src/render/light/mod.rs | 95 ++++++-------------------- 2 files changed, 22 insertions(+), 79 deletions(-) diff --git a/examples/testbed/testbed-renderdoc.cap b/examples/testbed/testbed-renderdoc.cap index cd8a585..5b5bac6 100644 --- a/examples/testbed/testbed-renderdoc.cap +++ b/examples/testbed/testbed-renderdoc.cap @@ -1,13 +1,13 @@ { "rdocCaptureSettings": 1, "settings": { - "autoStart": true, + "autoStart": false, "commandLine": "", "environment": [ ], "executable": "/media/data_drive/Development/Rust/lyra-engine/target/debug/testbed", "inject": false, - "numQueuedFrames": 1, + "numQueuedFrames": 0, "options": { "allowFullscreen": true, "allowVSync": true, @@ -22,7 +22,7 @@ "softMemoryLimit": 0, "verifyBufferAccess": false }, - "queuedFrameCap": 5, + "queuedFrameCap": 0, "workingDir": "/media/data_drive/Development/Rust/lyra-engine/examples/testbed" } } diff --git a/lyra-game/src/render/light/mod.rs b/lyra-game/src/render/light/mod.rs index 91b9ee6..6eb1db4 100644 --- a/lyra-game/src/render/light/mod.rs +++ b/lyra-game/src/render/light/mod.rs @@ -5,6 +5,7 @@ pub mod spotlight; use lyra_ecs::{Entity, Tick, World, query::{Entities, TickOf}}; pub use point::*; pub use spotlight::*; +use tracing::debug; use std::{collections::{HashMap, VecDeque}, marker::PhantomData, mem, rc::Rc}; @@ -99,12 +100,9 @@ impl LightBuffer { pub(crate) struct LightUniformBuffers { pub buffer: Rc, - //pub bind_group_pair: BindGroupPair, pub bind_group: Rc, pub bind_group_layout: Rc, - pub light_indexes: HashMap, - dead_indices: VecDeque, - pub current_light_idx: u32, + max_light_count: u64, } impl LightUniformBuffers { @@ -161,90 +159,35 @@ impl LightUniformBuffers { buffer: Rc::new(buffer), bind_group: Rc::new(bindgroup), bind_group_layout: Rc::new(bindgroup_layout), - light_indexes: Default::default(), - current_light_idx: 0, - dead_indices: VecDeque::new(), + max_light_count: max_buffer_sizes / mem::size_of::() as u64, } } - /// Returns the index for the entity, and if this index is new - fn get_index_for(&mut self, missed: &mut HashMap, entity: Entity) -> (bool, u32) { - let idx = missed.remove(&entity) - .map(|v| (false, v)) - .or_else(|| - self.dead_indices.pop_front() - .map(|v| (true, v)) - ) - .unwrap_or_else(|| { - let t = self.current_light_idx; - self.current_light_idx += 1; - (true, t) - }); - idx - } - pub fn update_lights(&mut self, queue: &wgpu::Queue, world_tick: Tick, world: &World) { - // used to detect what lights were removed - let mut missed_lights: HashMap = self.light_indexes.drain().collect(); - - for (entity, point_light, transform, light_epoch, transform_epoch) - in world.view_iter::<(Entities, &PointLight, &Transform, TickOf, TickOf)>() { + let _ = world_tick; + let mut lights = vec![]; - let (new, idx) = self.get_index_for(&mut missed_lights, entity); - self.light_indexes.insert(entity, idx); - - if new || light_epoch == world_tick || transform_epoch == world_tick { - let uniform = LightUniform::from_point_light_bundle(&point_light, &transform); - - let offset = mem::size_of::() * 4 + mem::size_of::() * idx as usize; - queue.write_buffer(&self.buffer, offset as _, bytemuck::cast_slice(&[uniform])); - } + for (point_light, transform) in world.view_iter::<(&PointLight, &Transform)>() { + let uniform = LightUniform::from_point_light_bundle(&point_light, &transform); + lights.push(uniform); } - for (entity, spot_light, transform, light_epoch, transform_epoch) - in world.view_iter::<(Entities, &SpotLight, &Transform, TickOf, TickOf)>() { - - let (new, idx) = self.get_index_for(&mut missed_lights, entity); - self.light_indexes.insert(entity, idx); - - if new || light_epoch == world_tick || transform_epoch == world_tick { - let uniform = LightUniform::from_spot_light_bundle(&spot_light, &transform); - - let offset = mem::size_of::() * 4 + mem::size_of::() * idx as usize; - queue.write_buffer(&self.buffer, offset as _, bytemuck::cast_slice(&[uniform])); - } + for (spot_light, transform) in world.view_iter::<(&SpotLight, &Transform)>() { + let uniform = LightUniform::from_spot_light_bundle(&spot_light, &transform); + lights.push(uniform); } - for (entity, dir_light, transform, light_epoch, transform_epoch) - in world.view_iter::<(Entities, &DirectionalLight, &Transform, TickOf, TickOf)>() { - - let (new, idx) = self.get_index_for(&mut missed_lights, entity); - self.light_indexes.insert(entity, idx); - - if new || light_epoch == world_tick || transform_epoch == world_tick { - let uniform = LightUniform::from_directional_bundle(&dir_light, &transform); - let offset = mem::size_of::() * 4 + mem::size_of::() * idx as usize; - queue.write_buffer(&self.buffer, offset as _, bytemuck::cast_slice(&[uniform])); - } + for (dir_light, transform) in world.view_iter::<(&DirectionalLight, &Transform)>() { + let uniform = LightUniform::from_directional_bundle(&dir_light, &transform); + lights.push(uniform); } - // anything left in missed_lights were lights that were deleted - let len = missed_lights.len(); - self.dead_indices.reserve(len); + assert!(lights.len() < self.max_light_count as _); // ensure we dont overwrite the buffer - for (_, v) in missed_lights.drain() { - // write zeros in place of this now dead light, the enabled boolean will be set to false - let mut zeros = Vec::new(); - zeros.resize(mem::size_of::(), 0u32); - - let offset = mem::size_of::() * 4 + mem::size_of::() * v as usize; - queue.write_buffer(&self.buffer, offset as _, bytemuck::cast_slice(zeros.as_slice())); - - self.dead_indices.push_back(v); - } - - // update the amount of lights, then the array of lights - queue.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[self.current_light_idx as u32])); + // write the amount of lights to the buffer, and right after that the list of lights. + queue.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[lights.len()])); + // the size of u32 is multiplied by 4 because of gpu alignment requirements + queue.write_buffer(&self.buffer, mem::size_of::() as u64 * 4, bytemuck::cast_slice(lights.as_slice())); } }