diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-07-11 18:00:08 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-07-11 18:00:08 -0700 |
| commit | 429dbcb9e0fcbb0b1c800f928cccc3b06800e6a4 (patch) | |
| tree | c2fa1b4a2723c69bf4118d8e2ed5efeee8f364c3 /src | |
| parent | 99e542e07cef78ef4af8e1443bd879b2565b3f61 (diff) | |
use an index buffer now, and draw two triangles
Force-Push: yes Change-Id: I2c58bad402908fa36caf271da3cae78e43ef3110
Diffstat (limited to 'src')
| -rw-r--r-- | src/graphics_window_dressing.rs | 137 | ||||
| -rw-r--r-- | src/linear_algebra.rs | 11 |
2 files changed, 95 insertions, 53 deletions
diff --git a/src/graphics_window_dressing.rs b/src/graphics_window_dressing.rs index f949af0..fb56fb3 100644 --- a/src/graphics_window_dressing.rs +++ b/src/graphics_window_dressing.rs @@ -3,7 +3,7 @@ use crate::error::*; use crate::graphics_permanent::{ PermanentGraphicsState, GraphicsStateForReinit, QueueFamilyIndices }; -use crate::linear_algebra::{ Vertex, VERTICES }; +use crate::linear_algebra::{ Vertex, VERTICES, INDICES }; use std::collections::BTreeSet; use std::ptr; @@ -40,6 +40,9 @@ pub struct WindowDressing { vertex_buffer: vk::Buffer, vertex_buffer_memory: vk::DeviceMemory, + index_buffer: vk::Buffer, + index_buffer_memory: vk::DeviceMemory, + pub command_buffers: Vec<vk::CommandBuffer>, pub concurrency: Concurrency, @@ -110,10 +113,14 @@ impl WindowDressing { let (vertex_buffer, vertex_buffer_memory) = init_vertex_buffer(instance, physical_device, device, graphics_queue, &transient_command_pool)?; + let (index_buffer, index_buffer_memory) + = init_index_buffer(instance, physical_device, device, + graphics_queue, &transient_command_pool)?; let command_buffers = init_commands(device, &swapchain.extent, &framebuffers, &render_pass, - &pipeline, &vertex_buffer, + &pipeline, + &vertex_buffer, &index_buffer, &primary_command_pool)?; let concurrency = init_concurrency(device, &swapchain.images)?; @@ -126,6 +133,8 @@ impl WindowDressing { framebuffers, vertex_buffer, vertex_buffer_memory, + index_buffer, + index_buffer_memory, primary_command_pool, transient_command_pool, command_buffers, @@ -164,7 +173,8 @@ impl WindowDressing { // Notice that we reused the command pool. let command_buffers = init_commands( device, &swapchain.extent, &framebuffers, &render_pass, - &pipeline, &self.vertex_buffer, &self.primary_command_pool)?; + &pipeline, &self.vertex_buffer, &self.index_buffer, + &self.primary_command_pool)?; self.concurrency.image_fences.resize(swapchain.images.len(), vk::Fence::null()); @@ -188,6 +198,8 @@ impl WindowDressing { unsafe { device.destroy_buffer(self.vertex_buffer, None) }; unsafe { device.free_memory(self.vertex_buffer_memory, None) }; + unsafe { device.destroy_buffer(self.index_buffer, None) }; + unsafe { device.free_memory(self.index_buffer_memory, None) }; for semaphore in self.concurrency.image_available_semaphores { unsafe { device.destroy_semaphore(semaphore, None) }; @@ -540,20 +552,41 @@ fn init_framebuffers(device: &Device, extent: &vk::Extent2D, } -#[allow(unsafe_code)] fn init_vertex_buffer(instance: &Instance, physical_device: &vk::PhysicalDevice, device: &Device, queue: &vk::Queue, command_pool: &vk::CommandPool) -> Result<(vk::Buffer, vk::DeviceMemory)> { - let size = (size_of::<Vertex<f32>>() * VERTICES.len()) as u64; + init_buffer(instance, physical_device, device, queue, command_pool, + vk::BufferUsageFlags::VERTEX_BUFFER, &VERTICES) +} + + +fn init_index_buffer(instance: &Instance, + physical_device: &vk::PhysicalDevice, device: &Device, + queue: &vk::Queue, command_pool: &vk::CommandPool) + -> Result<(vk::Buffer, vk::DeviceMemory)> +{ + init_buffer(instance, physical_device, device, queue, command_pool, + vk::BufferUsageFlags::INDEX_BUFFER, INDICES) +} + + +#[allow(unsafe_code)] +fn init_buffer<T>(instance: &Instance, + physical_device: &vk::PhysicalDevice, device: &Device, + queue: &vk::Queue, command_pool: &vk::CommandPool, + usage: vk::BufferUsageFlags, contents: &[T]) + -> Result<(vk::Buffer, vk::DeviceMemory)> +{ + let size = (size_of::<T>() * contents.len()) as u64; let staging_usage = vk::BufferUsageFlags::TRANSFER_SRC; let staging_memory_flags = vk::MemoryPropertyFlags::HOST_COHERENT | vk::MemoryPropertyFlags::HOST_VISIBLE; let (staging_buffer, staging_memory) - = init_buffer(instance, physical_device, device, - size, staging_usage, staging_memory_flags)?; + = allocate_buffer(instance, physical_device, device, + size, staging_usage, staging_memory_flags)?; let host_memory = unsafe { device.map_memory(staging_memory, 0, size, vk::MemoryMapFlags::empty()) @@ -561,17 +594,16 @@ fn init_vertex_buffer(instance: &Instance, unsafe { ptr::copy_nonoverlapping( - VERTICES.as_ptr(), host_memory.cast(), VERTICES.len()) + contents.as_ptr(), host_memory.cast(), contents.len()) }; unsafe { device.unmap_memory(staging_memory) }; - let final_usage = vk::BufferUsageFlags::TRANSFER_DST - | vk::BufferUsageFlags::VERTEX_BUFFER; + let final_usage = vk::BufferUsageFlags::TRANSFER_DST | usage; let final_memory_flags = vk::MemoryPropertyFlags::DEVICE_LOCAL; let (final_buffer, device_memory) - = init_buffer(instance, physical_device, device, - size, final_usage, final_memory_flags)?; + = allocate_buffer(instance, physical_device, device, + size, final_usage, final_memory_flags)?; copy_buffer(device, queue, command_pool, &staging_buffer, &final_buffer, size)?; @@ -584,42 +616,6 @@ fn init_vertex_buffer(instance: &Instance, #[allow(unsafe_code)] -fn init_buffer(instance: &Instance, - physical_device: &vk::PhysicalDevice, device: &Device, - size: vk::DeviceSize, usage: vk::BufferUsageFlags, - memory_flags: vk::MemoryPropertyFlags) - -> Result<(vk::Buffer, vk::DeviceMemory)> -{ - let buffer_info = vk::BufferCreateInfo::builder() - .size(size) - .usage(usage) - .sharing_mode(vk::SharingMode::EXCLUSIVE); - - let buffer = unsafe { device.create_buffer(&buffer_info, None) }?; - - // The requirements are mostly what you'd think: size and alignment. The - // bits field is something special; see pick_memory_type() for the - // explanation. Despite the simplicity of this data, Vulkan wants to be the - // one to tell us about it, and we let it. - let requirements = unsafe { device.get_buffer_memory_requirements(buffer) }; - - let type_index = pick_memory_type(instance, physical_device, - &memory_flags, &requirements)?; - - - let memory_info = vk::MemoryAllocateInfo::builder() - .allocation_size(requirements.size) - .memory_type_index(type_index); - - let device_memory = unsafe { device.allocate_memory(&memory_info, None) }?; - - unsafe { device.bind_buffer_memory(buffer, device_memory, 0) }?; - - Ok((buffer, device_memory)) -} - - -#[allow(unsafe_code)] fn init_command_pools(device: &Device, indices: &QueueFamilyIndices) -> Result<(vk::CommandPool, vk::CommandPool)> { @@ -647,6 +643,7 @@ fn init_commands(device: &Device, render_pass: &vk::RenderPass, pipeline: &vk::Pipeline, vertex_buffer: &vk::Buffer, + index_buffer: &vk::Buffer, command_pool: &vk::CommandPool) -> Result<Vec<vk::CommandBuffer>> { @@ -706,7 +703,13 @@ fn init_commands(device: &Device, }; unsafe { - device.cmd_draw(command_buffer, VERTICES.len() as u32, 1, 0, 0) + device.cmd_bind_index_buffer(command_buffer, *index_buffer, 0, + vk::IndexType::UINT16) + }; + + unsafe { + device.cmd_draw_indexed(command_buffer, INDICES.len() as u32, + 1, 0, 0, 0) }; unsafe { device.cmd_end_render_pass(command_buffer) }; @@ -838,6 +841,42 @@ fn pick_memory_type(instance: &Instance, #[allow(unsafe_code)] +fn allocate_buffer(instance: &Instance, + physical_device: &vk::PhysicalDevice, device: &Device, + size: vk::DeviceSize, usage: vk::BufferUsageFlags, + memory_flags: vk::MemoryPropertyFlags) + -> Result<(vk::Buffer, vk::DeviceMemory)> +{ + let buffer_info = vk::BufferCreateInfo::builder() + .size(size) + .usage(usage) + .sharing_mode(vk::SharingMode::EXCLUSIVE); + + let buffer = unsafe { device.create_buffer(&buffer_info, None) }?; + + // The requirements are mostly what you'd think: size and alignment. The + // bits field is something special; see pick_memory_type() for the + // explanation. Despite the simplicity of this data, Vulkan wants to be the + // one to tell us about it, and we let it. + let requirements = unsafe { device.get_buffer_memory_requirements(buffer) }; + + let type_index = pick_memory_type(instance, physical_device, + &memory_flags, &requirements)?; + + + let memory_info = vk::MemoryAllocateInfo::builder() + .allocation_size(requirements.size) + .memory_type_index(type_index); + + let device_memory = unsafe { device.allocate_memory(&memory_info, None) }?; + + unsafe { device.bind_buffer_memory(buffer, device_memory, 0) }?; + + Ok((buffer, device_memory)) +} + + +#[allow(unsafe_code)] fn copy_buffer(device: &Device, queue: &vk::Queue, command_pool: &vk::CommandPool, source: &vk::Buffer, destination: &vk::Buffer, diff --git a/src/linear_algebra.rs b/src/linear_algebra.rs index 950877b..9b3ef73 100644 --- a/src/linear_algebra.rs +++ b/src/linear_algebra.rs @@ -3,12 +3,15 @@ use std::mem::size_of; use vulkanalia::vk::{ self, HasBuilder }; -pub static VERTICES: [Vertex<f32>; 3] = [ - Vertex::new(Vec2( 0.0, -0.5), Vec3(1.0, 0.0, 0.0)), - Vertex::new(Vec2( 0.5, 0.5), Vec3(0.0, 1.0, 0.0)), - Vertex::new(Vec2(-0.5, 0.5), Vec3(0.0, 0.0, 1.0)), +pub static VERTICES: [Vertex<f32>; 4] = [ + Vertex::new(Vec2(-0.5, -0.5), Vec3(1.0, 0.0, 0.0)), + Vertex::new(Vec2( 0.5, -0.5), Vec3(0.0, 1.0, 0.0)), + Vertex::new(Vec2( 0.5, 0.5), Vec3(0.0, 0.0, 1.0)), + Vertex::new(Vec2(-0.5, 0.5), Vec3(1.0, 1.0, 1.0)), ]; +pub const INDICES: &[u16] = &[0, 1, 2, 2, 3, 0]; + #[derive(Clone, Debug)] pub struct Vec2<T>(T, T); |