From dd61e8e66cb1bbffc2bd64261e747fbc567babc6 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sun, 31 Mar 2024 23:02:18 -0400 Subject: [PATCH] render: hack to get rendering shared 3d modules working --- lyra-game/src/render/render_job.rs | 4 +- lyra-game/src/render/renderer.rs | 21 ++- .../src/render/transform_buffer_storage.rs | 153 ++++++------------ 3 files changed, 66 insertions(+), 112 deletions(-) diff --git a/lyra-game/src/render/render_job.rs b/lyra-game/src/render/render_job.rs index 90809b8..8a6d72d 100755 --- a/lyra-game/src/render/render_job.rs +++ b/lyra-game/src/render/render_job.rs @@ -4,14 +4,16 @@ pub struct RenderJob { pub entity: Entity, pub shader_id: u64, pub mesh_uuid: uuid::Uuid, + pub transform_id: u32, } impl RenderJob { - pub fn new(entity: Entity, shader_id: u64, mesh_buffer_id: uuid::Uuid) -> Self { + pub fn new(entity: Entity, shader_id: u64, mesh_buffer_id: uuid::Uuid, transform_id: u32) -> Self { Self { entity, shader_id, mesh_uuid: mesh_buffer_id, + transform_id } } } \ No newline at end of file diff --git a/lyra-game/src/render/renderer.rs b/lyra-game/src/render/renderer.rs index 295243c..5015e9c 100755 --- a/lyra-game/src/render/renderer.rs +++ b/lyra-game/src/render/renderer.rs @@ -374,12 +374,13 @@ impl BasicRenderer { /// Processes the mesh for the renderer, storing and creating buffers as needed. Returns true if a new mesh was processed. fn process_mesh(&mut self, entity: Entity, transform: Transform, mesh: &Mesh, mesh_uuid: Uuid) -> bool { - if self.transform_buffers.should_expand() { + let _ = transform; + /* if self.transform_buffers.should_expand() { self.transform_buffers.expand_buffers(&self.device); } self.transform_buffers.update_or_insert(&self.queue, &self.render_limits, - mesh_uuid, || ( transform.calculate_mat4(), glam::Mat3::from_quat(transform.rotation) )); + entity, || ( transform.calculate_mat4(), glam::Mat3::from_quat(transform.rotation) )); */ #[allow(clippy::map_entry)] if !self.mesh_buffers.contains_key(&mesh_uuid) { @@ -451,10 +452,12 @@ impl Renderer for BasicRenderer { self.check_mesh_buffers(entity, &mesh_han); } + let transform_id = self.transform_buffers.push_transform(&self.queue, &self.render_limits, interop_pos.calculate_mat4(), glam::Mat3::from_quat(interop_pos.rotation)); + let material = mesh.material.as_ref().unwrap() .data_ref().unwrap(); let shader = material.shader_uuid.unwrap_or(0); - let job = RenderJob::new(entity, shader, mesh_han.uuid()); + let job = RenderJob::new(entity, shader, mesh_han.uuid(), transform_id); self.render_jobs.push_back(job); } } @@ -478,11 +481,13 @@ impl Renderer for BasicRenderer { && scene_epoch == last_epoch { self.check_mesh_buffers(entity, &mesh_han); } + + let transform_id = self.transform_buffers.push_transform(&self.queue, &self.render_limits, mesh_interpo.calculate_mat4(), glam::Mat3::from_quat(mesh_interpo.rotation)); let material = mesh.material.as_ref().unwrap() .data_ref().unwrap(); let shader = material.shader_uuid.unwrap_or(0); - let job = RenderJob::new(entity, shader, mesh_han.uuid()); + let job = RenderJob::new(entity, shader, mesh_han.uuid(), transform_id); self.render_jobs.push_back(job); } } @@ -576,9 +581,11 @@ impl Renderer for BasicRenderer { } // Get the bindgroup for job's transform and bind to it using an offset. - let transform_indices = *self.transform_buffers.transform_indices(job.mesh_uuid).unwrap(); - let bindgroup = self.transform_buffers.bind_group(transform_indices).unwrap(); - let offset = TransformBuffers::index_offset(&self.render_limits, transform_indices) as u32; + /* let transform_indices = *self.transform_buffers.transform_indices(job.entity).unwrap(); + let bindgroup = self.transform_buffers.bind_group(transform_indices).unwrap(); */ + + let bindgroup = self.transform_buffers.bind_group(job.transform_id); + let offset = self.transform_buffers.buffer_offset(job.transform_id);//TransformBuffers::index_offset(&self.render_limits, transform_indices) as u32; render_pass.set_bind_group(1, bindgroup, &[ offset, offset, ]); render_pass.set_bind_group(2, &self.camera_buffer.bindgroup(), &[]); diff --git a/lyra-game/src/render/transform_buffer_storage.rs b/lyra-game/src/render/transform_buffer_storage.rs index 4223df5..0db9851 100644 --- a/lyra-game/src/render/transform_buffer_storage.rs +++ b/lyra-game/src/render/transform_buffer_storage.rs @@ -1,6 +1,5 @@ -use std::{collections::{VecDeque, HashMap}, num::NonZeroU64}; +use std::num::NonZeroU64; -use uuid::Uuid; use wgpu::Limits; use std::mem; @@ -14,9 +13,9 @@ pub(crate) struct TransformBufferIndices { /// A struct representing a single transform buffer. There can be multiple of these pub(crate) struct TransformBufferEntry { pub len: usize, - pub transform_buf: wgpu::Buffer, - pub normal_mat_buf: wgpu::Buffer, pub bindgroup: wgpu::BindGroup, + pub transform_buffer: wgpu::Buffer, + pub normal_buffer: wgpu::Buffer, } /// A helper struct for managing the Transform buffers for meshes. @@ -31,14 +30,8 @@ pub(crate) struct TransformBufferEntry { /// to insert, update, and retrieve the transforms. pub(crate) struct TransformBuffers { pub bindgroup_layout: wgpu::BindGroupLayout, - pub just_updated: HashMap, - pub not_updated: HashMap, - pub dead_indices: VecDeque, - pub next_indices: TransformBufferIndices, - /// (transform count, buffer, bindgroup) - pub buffer_bindgroups: Vec, - /// The max amount of transforms in a buffer - pub max_transform_count: usize, + pub entries: Vec, + limits: wgpu::Limits, } impl TransformBuffers { @@ -72,13 +65,9 @@ impl TransformBuffers { }); let mut s = Self { - max_transform_count: limits.max_uniform_buffer_binding_size as usize / (mem::size_of::() * 2), - buffer_bindgroups: Vec::new(), bindgroup_layout, - just_updated: HashMap::new(), - not_updated: HashMap::new(), - dead_indices: VecDeque::new(), - next_indices: TransformBufferIndices::default(), + entries: vec![], + limits, }; // create the first uniform buffer @@ -87,95 +76,29 @@ impl TransformBuffers { s } - /// Update an transform in the buffer. - /// - /// # Panics - /// Panics if the entity isn't stored, you can check if it is before with [`TransformBuffers:contains`]. - pub fn update_transform(&mut self, queue: &wgpu::Queue, limits: &Limits, uuid: Uuid, transform: glam::Mat4, normal_matrix: glam::Mat3) -> TransformBufferIndices { - let indices = self.not_updated.remove(&uuid) - .or_else(|| self.just_updated.remove(&uuid)) - .expect("Use 'insert_entity' for new entities"); - self.just_updated.insert(uuid, indices); + pub fn push_transform(&mut self, queue: &wgpu::Queue, limits: &Limits, transform: glam::Mat4, normal_matrix: glam::Mat3) -> u32 { + let entry = self.entries.iter_mut().next().unwrap(); // TODO: use other buffers than just the first let normal_matrix = glam::Mat4::from_mat3(normal_matrix); - let buffer = self.buffer_bindgroups.get(indices.buffer_index).unwrap(); - let offset = Self::index_offset(limits, indices); - queue.write_buffer(&buffer.transform_buf, offset, bytemuck::bytes_of(&transform)); - queue.write_buffer(&buffer.normal_mat_buf, offset, bytemuck::bytes_of(&normal_matrix)); - indices - } + // write the transform and normal to the end of the transform + //let offset = (mem::size_of::() * entry.len) as u64; + let offset = Self::get_buffer_offset(limits, entry.len as u32) as _; + queue.write_buffer(&entry.transform_buffer, offset, bytemuck::bytes_of(&transform)); + queue.write_buffer(&entry.normal_buffer, offset, bytemuck::bytes_of(&normal_matrix)); - /// Insert a new transform into the buffer, returns where in the buffer it was stored. - pub fn insert_transform(&mut self, queue: &wgpu::Queue, limits: &Limits, uuid: Uuid, transform: glam::Mat4, normal_matrix: glam::Mat3) -> TransformBufferIndices { - let indices = match self.dead_indices.pop_front() { - Some(indices) => indices, - None => { - let indices = &mut self.next_indices; - let this_idx = *indices; - let entry = self.buffer_bindgroups.get_mut(indices.buffer_index).unwrap(); - - if entry.len >= self.max_transform_count { - panic!("Transform buffer is filled and 'next_indices' was not incremented! Was a new buffer created?"); - } - - entry.len += 1; - indices.transform_index += 1; - this_idx - } - }; - - self.just_updated.insert(uuid, indices); - self.update_transform(queue, limits, uuid, transform, normal_matrix) - } - - /// Update or insert a transform - pub fn update_or_insert(&mut self, queue: &wgpu::Queue, limits: &Limits, uuid: Uuid, transform_fn: TFn) -> TransformBufferIndices - where TFn: Fn() -> (glam::Mat4, glam::Mat3) - { - let (tran, norm) = transform_fn(); - if self.contains(uuid) { - self.update_transform(queue, limits, uuid, tran, norm) - } else { - self.insert_transform(queue, limits, uuid, tran, norm) - } - } - - /// Returns true if the transform related to the `uuid` is stored (does not mean its up-to-date). - pub fn contains(&self, uuid: Uuid) -> bool { - self.not_updated.contains_key(&uuid) || self.just_updated.contains_key(&uuid) + let index = entry.len; + entry.len += 1; + index as _ } /// Collect the dead transforms and prepare self to check next time. pub fn tick(&mut self) { - // take the dead entities, these were ones that were not updated this tick - let dead: VecDeque = self.not_updated.values().copied().collect(); - self.dead_indices = dead; - - self.not_updated = self.just_updated.clone(); - self.just_updated.clear(); - } - - /// Returns the offset for the transform index in the buffer - pub fn index_offset(limits: &Limits, indices: TransformBufferIndices) -> u64 { - indices.transform_index as u64 * limits.min_uniform_buffer_offset_alignment as u64 - } - - /// Returns whether or not the transform buffers should be expanded - pub fn should_expand(&self) -> bool { - if let Some(entry) = self.buffer_bindgroups.last() { - entry.len >= self.max_transform_count - } else { - true + for entry in self.entries.iter_mut() { + entry.len = 0; } } - /// Returns the bind group for the index - pub fn bind_group(&self, index: TransformBufferIndices) -> Option<&wgpu::BindGroup> { - self.buffer_bindgroups.get(index.buffer_index) - .map(|entry| &entry.bindgroup) - } - /// Expand the Transform buffers by adding another uniform buffer binding. /// /// This object has a chain of uniform buffers, when the buffers are expanded, a new @@ -186,7 +109,7 @@ impl TransformBuffers { let transform_buffer = device.create_buffer( &wgpu::BufferDescriptor { - label: Some(&format!("B_Transform_{}", self.buffer_bindgroups.len())), + label: Some(&format!("B_Transform_{}", self.entries.len())), usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, size: max_buffer_sizes, mapped_at_creation: false, @@ -195,7 +118,7 @@ impl TransformBuffers { let normal_mat_buffer = device.create_buffer( &wgpu::BufferDescriptor { - label: Some(&format!("B_NormalMatrix_{}", self.buffer_bindgroups.len())), + label: Some(&format!("B_NormalMatrix_{}", self.entries.len())), usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, size: max_buffer_sizes, mapped_at_creation: false, @@ -236,15 +159,37 @@ impl TransformBuffers { let entry = TransformBufferEntry { bindgroup: transform_bind_group, - transform_buf: transform_buffer, - normal_mat_buf: normal_mat_buffer, + transform_buffer, + normal_buffer: normal_mat_buffer, len: 0, }; - self.buffer_bindgroups.push(entry); + self.entries.push(entry); } - /// Returns the indices of the Transform - pub fn transform_indices(&self, uuid: Uuid) -> Option<&TransformBufferIndices> { - self.just_updated.get(&uuid).or_else(|| self.not_updated.get(&uuid)) + pub fn bind_group(&self, transform_id: u32) -> &wgpu::BindGroup { + let _ = transform_id; + + let entry = self.entries.iter().next().unwrap(); // TODO: use other buffers than just the first + &entry.bindgroup } + + /// Get the buffer offset for a transform using wgpu limits. + /// + /// If its possible to borrow immutably, use [`TransformBuffers::buffer_offset`]. + fn get_buffer_offset(limits: &wgpu::Limits, transform_id: u32) -> u32 { + //let entry = self.entries.iter().next().unwrap(); // TODO: use other buffers than just the first + + transform_id * limits.min_uniform_buffer_offset_alignment as u32//mem::size_of::() as u32 + } + + pub fn buffer_offset(&self, transform_id: u32) -> u32 { + Self::get_buffer_offset(&self.limits, transform_id) + } +} + +#[repr(C)] +#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct TransformNormalMatPair { + transform: glam::Mat4, + normal_mat: glam::Mat4, } \ No newline at end of file