summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-07-11 18:00:08 -0700
committerIrene Knapp <ireneista@irenes.space>2026-07-11 18:00:08 -0700
commit429dbcb9e0fcbb0b1c800f928cccc3b06800e6a4 (patch)
treec2fa1b4a2723c69bf4118d8e2ed5efeee8f364c3 /src
parent99e542e07cef78ef4af8e1443bd879b2565b3f61 (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.rs137
-rw-r--r--src/linear_algebra.rs11
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);