From e6f84148174fa79e3ecd437c87c84e13f11fd561 Mon Sep 17 00:00:00 2001 From: Serkyo Date: Mon, 11 May 2026 00:04:42 +0200 Subject: [PATCH] feat(renderer): implement vertex buffer allocation and memory mapping --- crates/renderer/src/error.rs | 6 +++++ crates/renderer/src/lib.rs | 47 +++++++++++++++++++++++++++++++++ crates/renderer/src/renderer.rs | 11 +++++++- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/crates/renderer/src/error.rs b/crates/renderer/src/error.rs index e6132db..ac3c6e1 100644 --- a/crates/renderer/src/error.rs +++ b/crates/renderer/src/error.rs @@ -2,10 +2,16 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum RendererError { + /// The Vulkan library could not be loaded from the system. #[error("Failed to load Vulkan library")] LoadFailed(#[from] ash::LoadingError), + /// A raw Vulkan result indicated a failure. #[error("Vulkan error")] VulkanError(#[from] ash::vk::Result), + /// No GPU was found that meets the engine's requirements. #[error("No suitable GPU found")] NoSuitableGpu, + /// An error occurred during GPU memory allocation. + #[error("GPU allocation error")] + AllocationError(#[from] gpu_allocator::AllocationError), } \ No newline at end of file diff --git a/crates/renderer/src/lib.rs b/crates/renderer/src/lib.rs index 7929feb..9b706c6 100644 --- a/crates/renderer/src/lib.rs +++ b/crates/renderer/src/lib.rs @@ -89,6 +89,8 @@ impl Renderer { let sync = sync::create_sync_primitives(&device, MAX_FRAMES_IN_FLIGHT, swapchain_images.len())?; + // 11. GPU Memory Allocator + // The allocator handles the complexity of sub-allocating memory blocks from the GPU. let allocator_create_info = gpu_allocator::vulkan::AllocatorCreateDesc { instance: instance.clone(), device: device.clone(), @@ -101,10 +103,53 @@ impl Renderer { let allocator = gpu_allocator::vulkan::Allocator::new(&allocator_create_info) .expect("Failed to create Vulkan allocator"); + // 12. Graphics Pipeline Configuration + // The pipeline defines the fixed-function and programmable state for rendering voxel geometry. let pipeline_layout = pipeline::create_pipeline_layout(&device); let graphics_pipeline = pipeline::create_graphics_pipeline(&device, pipeline_layout, swapchain_format); + // 13. Vertex Buffer Initialization + // A simple triangle is defined in normalized device coordinates and moved to GPU memory. + let vertices = [ + mesh::Vertex { position: [0.0, -0.5, 0.0], tex_coord: [0.5, 0.0] }, + mesh::Vertex { position: [0.5, 0.5, 0.0], tex_coord: [1.0, 1.0] }, + mesh::Vertex { position: [-0.5, 0.5, 0.0], tex_coord: [0.0, 1.0] }, + ]; + + // Create the buffer handle and query its memory requirements. + let buffer_info = vk::BufferCreateInfo::default() + .size(std::mem::size_of_val(&vertices) as u64) + .usage(vk::BufferUsageFlags::VERTEX_BUFFER); + + let vertex_buffer = unsafe { device.create_buffer(&buffer_info, None)? }; + let requirements = unsafe { device.get_buffer_memory_requirements(vertex_buffer) }; + + let mut allocator = allocator; + + // Allocate memory that is visible to the CPU for data transfer. + let vertex_allocation = allocator.allocate(&gpu_allocator::vulkan::AllocationCreateDesc { + name: "Vertex Buffer", + requirements, + location: gpu_allocator::MemoryLocation::CpuToGpu, + linear: true, + allocation_scheme: gpu_allocator::vulkan::AllocationScheme::GpuAllocatorManaged, + })?; + + // Bind the allocated memory to the buffer handle and copy the vertex data. + unsafe { + device.bind_buffer_memory(vertex_buffer, vertex_allocation.memory(), vertex_allocation.offset())?; + + let ptr = vertex_allocation.mapped_ptr() + .expect("Failed to map vertex buffer memory") + .as_ptr(); + + std::ptr::copy_nonoverlapping( + vertices.as_ptr() as *const u8, + ptr as *mut u8, + std::mem::size_of_val(&vertices)); + } + Ok(Self { _entry: entry, instance, @@ -127,6 +172,8 @@ impl Renderer { allocator, pipeline_layout, graphics_pipeline, + vertex_buffer, + vertex_allocation, sync, current_frame: 0, }) diff --git a/crates/renderer/src/renderer.rs b/crates/renderer/src/renderer.rs index 3fc771e..66c4a3b 100644 --- a/crates/renderer/src/renderer.rs +++ b/crates/renderer/src/renderer.rs @@ -1,7 +1,7 @@ use crate::error::RendererError; use crate::sync::SyncPrimitives; use ash::{Device, Instance, khr, vk}; -use gpu_allocator::vulkan::Allocator; +use gpu_allocator::vulkan::{Allocation, Allocator}; @@ -49,6 +49,10 @@ pub struct Renderer { pub(crate) graphics_pipeline: vk::Pipeline, /// Memory manager for GPU allocations. pub(crate) allocator: Allocator, + /// Buffer containing the vertex data for the initial triangle. + pub(crate) vertex_buffer: vk::Buffer, + /// Memory allocation for the vertex buffer. + pub(crate) vertex_allocation: Allocation, /// Synchronization primitives for frame-by-frame execution. pub(crate) sync: SyncPrimitives, /// Index of the current frame being processed (0 to crate::MAX_FRAMES_IN_FLIGHT - 1). @@ -202,6 +206,11 @@ impl Drop for Renderer { self.device .destroy_pipeline_layout(self.pipeline_layout, None); + self.allocator.free(std::ptr::read(&self.vertex_allocation)) + .expect(" Failed to free vertex buffer allocation"); + + self.device.destroy_buffer(self.vertex_buffer, None); + self.device.destroy_command_pool(self.command_pool, None); // Use the safe cleanup function from sync module