From 429dbcb9e0fcbb0b1c800f928cccc3b06800e6a4 Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Sat, 11 Jul 2026 18:00:08 -0700 Subject: use an index buffer now, and draw two triangles Force-Push: yes Change-Id: I2c58bad402908fa36caf271da3cae78e43ef3110 --- src/graphics_window_dressing.rs | 137 ++++++++++++++++++++++++++-------------- 1 file changed, 88 insertions(+), 49 deletions(-) (limited to 'src/graphics_window_dressing.rs') 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, 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::>() * 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(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::() * 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)?; @@ -583,42 +615,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> { @@ -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) }; @@ -837,6 +840,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, -- cgit 1.4.1