From 203cc2a6715dbee3f81c20f7306d3d5f0b78cedc Mon Sep 17 00:00:00 2001 From: Serkyo Date: Sat, 16 May 2026 19:04:20 +0200 Subject: [PATCH] feat(renderer): add dynamic mesh updates via buffer reallocation --- crates/renderer/src/lib.rs | 5 +++- crates/renderer/src/mesh.rs | 5 ++++ crates/renderer/src/renderer.rs | 53 +++++++++++++++++++++++++++++---- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/crates/renderer/src/lib.rs b/crates/renderer/src/lib.rs index b6b90e6..5d03e2a 100644 --- a/crates/renderer/src/lib.rs +++ b/crates/renderer/src/lib.rs @@ -8,7 +8,7 @@ mod device; pub mod error; mod instance; -mod mesh; +pub mod mesh; mod pipeline; mod renderer; mod surface; @@ -119,6 +119,8 @@ impl Renderer { let (vertex_buffer, vertex_allocation, index_buffer, index_allocation) = create_geometry(&device, &mut allocator)?; + let index_count = 36; + let (depth_image, depth_allocation, depth_image_view) = create_depth_resources(&device, &mut allocator, swapchain_extent)?; @@ -144,6 +146,7 @@ impl Renderer { allocator, index_buffer, index_allocation, + index_count, depth_image, depth_allocation, depth_image_view, diff --git a/crates/renderer/src/mesh.rs b/crates/renderer/src/mesh.rs index 51bd690..6c4c8ec 100644 --- a/crates/renderer/src/mesh.rs +++ b/crates/renderer/src/mesh.rs @@ -10,7 +10,9 @@ use bytemuck::{Pod, Zeroable}; #[derive(Copy, Clone, Debug, Pod, Zeroable)] pub struct Vertex { /// 3D position of the vertex (X, Y, Z). + /// The position coordinates of the vertex [x, y, z]. pub position: [f32; 3], + /// The RGB color of the vertex [r, g, b]. pub color: [f32; 3], } @@ -19,6 +21,9 @@ impl Vertex { /// /// This defines the 'stride' (distance between vertices) and specifies that /// data is read per-vertex rather than per-instance. + /// + /// # Panics + /// Panics if the size of the vertex structure exceeds the maximum value of a 32-bit unsigned integer. #[allow(clippy::expect_used)] pub fn get_binding_description() -> ash::vk::VertexInputBindingDescription { ash::vk::VertexInputBindingDescription::default() diff --git a/crates/renderer/src/renderer.rs b/crates/renderer/src/renderer.rs index 79dfb5c..184196a 100644 --- a/crates/renderer/src/renderer.rs +++ b/crates/renderer/src/renderer.rs @@ -1,4 +1,5 @@ -use crate::error::RendererError; +use crate::create_gpu_buffer; +use crate::{error::RendererError, mesh::Vertex}; use crate::sync::SyncPrimitives; use ash::{Device, Instance, khr, vk}; use gpu_allocator::vulkan::{Allocation, Allocator}; @@ -58,6 +59,7 @@ pub struct Renderer { pub(crate) index_buffer: vk::Buffer, /// Memory allocation for the index buffer. pub(crate) index_allocation: Allocation, + pub(crate) index_count: u32, /// The depth image used for depth testing. pub(crate) depth_image: vk::Image, /// Image view for the depth buffer. @@ -276,12 +278,12 @@ impl Renderer { f64::from(self.swapchain_extent.width) / f64::from(self.swapchain_extent.height); #[allow(clippy::cast_possible_truncation)] let mut projection = - glam::Mat4::perspective_rh(45.0_f32.to_radians(), aspect as f32, 0.1, 100.0); + glam::Mat4::perspective_rh(45.0_f32.to_radians(), aspect as f32, 0.1, 500.0); projection.col_mut(1).y *= -1.0; let view = glam::Mat4::look_at_rh( - glam::vec3(2.0, 2.0, 2.0), - glam::vec3(0.0, 0.0, 0.0), + glam::vec3(16.0, 40.0, 60.0), + glam::vec3(16.0, 16.0, 16.0), glam::vec3(0.0, 1.0, 0.0), ); @@ -297,7 +299,7 @@ impl Renderer { mvp_bytes, ); - self.device.cmd_draw_indexed(cmd, 36, 1, 0, 0, 0); + self.device.cmd_draw_indexed(cmd, self.index_count, 1, 0, 0, 0); } } @@ -335,6 +337,47 @@ impl Renderer { Ok(()) } + + /// Replaces the currently rendering mesh with a new set of vertices and indices. + /// + /// # Errors + /// Returns a `RendererError` if new Vulkan buffers cannot be allocated or created. + #[allow(clippy::cast_possible_truncation)] + pub fn update_mesh(&mut self, vertices: &[Vertex], indices: &[u32]) -> Result<(), RendererError> { + unsafe { + let _ = self.device.device_wait_idle(); + + let _ = self.allocator.free(std::ptr::read(&raw const self.vertex_allocation)); + self.device.destroy_buffer(self.vertex_buffer, None); + + let _ = self.allocator.free(std::ptr::read(&raw const self.index_allocation)); + self.device.destroy_buffer(self.index_buffer, None); + } + + let (v_buf, v_alloc) = create_gpu_buffer( + &self.device, + &mut self.allocator, + bytemuck::cast_slice(vertices), + vk::BufferUsageFlags::VERTEX_BUFFER, + "Chunk Vertex Buffer", + )?; + + let (i_buf, i_alloc) = crate::create_gpu_buffer( + &self.device, + &mut self.allocator, + bytemuck::cast_slice(indices), + vk::BufferUsageFlags::INDEX_BUFFER, + "Chunk Index Buffer", + )?; + + self.vertex_buffer = v_buf; + self.vertex_allocation = v_alloc; + self.index_buffer = i_buf; + self.index_allocation = i_alloc; + self.index_count = indices.len() as u32; + + Ok(()) + } } impl Drop for Renderer {