summary refs log tree commit diff
path: root/src/graphics/model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics/model.rs')
-rw-r--r--src/graphics/model.rs141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/graphics/model.rs b/src/graphics/model.rs
new file mode 100644
index 0000000..b691d99
--- /dev/null
+++ b/src/graphics/model.rs
@@ -0,0 +1,141 @@
+#![deny(unsafe_code)]
+use crate::error::*;
+use crate::graphics::permanent::{
+  PermanentGraphicsState, GraphicsStateForReinit
+};
+use crate::graphics::render_state::RenderState;
+use crate::graphics::util::init_buffer;
+use crate::graphics::window_dressing::WindowDressing;
+use crate::linear_algebra::{ Vec3, Vec4, Transformation };
+use crate::model_loader::load_model;
+use crate::shader_data::{ Vertex, VertexPushBlock };
+
+use std::f32::consts::{ TAU };
+
+use vulkanalia::{ Device, Instance };
+use vulkanalia::vk::{ self, DeviceV1_0 };
+
+
+#[derive(Debug)]
+pub struct Model {
+  pub vertex_buffer: vk::Buffer,
+  vertex_buffer_memory: vk::DeviceMemory,
+
+  pub index_buffer: vk::Buffer,
+  index_buffer_memory: vk::DeviceMemory,
+  pub index_count: usize,
+}
+
+
+impl Model {
+  pub fn new(permanent: &PermanentGraphicsState,
+             for_reinit: &GraphicsStateForReinit,
+             window_dressing: &WindowDressing)
+      -> Result<Self>
+  {
+    let device = &permanent.device;
+    let instance = &permanent.instance;
+    let graphics_queue = &permanent.graphics_queue;
+    let physical_device = &for_reinit.physical_device;
+    let transient_command_pool = &window_dressing.transient_command_pool;
+
+    let (vertices, indices) = load_model()?;
+    let index_count = indices.len();
+
+    let (vertex_buffer, vertex_buffer_memory)
+            = init_vertex_buffer(vertices, instance, physical_device, device,
+                                 graphics_queue, &transient_command_pool)?;
+    let (index_buffer, index_buffer_memory)
+            = init_index_buffer(indices, instance, physical_device, device,
+                                graphics_queue, &transient_command_pool)?;
+
+    Ok(Model {
+      vertex_buffer,
+      vertex_buffer_memory,
+      index_buffer,
+      index_buffer_memory,
+      index_count,
+    })
+  }
+
+  #[allow(unsafe_code)]
+  pub fn destroy(self, device: &Device) {
+    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) };
+  }
+
+  #[allow(unsafe_code)]
+  pub fn render(&self, time: f32, device: &Device, render_state: &RenderState,
+                command_buffer: &vk::CommandBuffer,
+                descriptor_set: &vk::DescriptorSet)
+  {
+    unsafe {
+      device.cmd_bind_vertex_buffers(*command_buffer, 0,
+                                     &[self.vertex_buffer], &[0])
+    };
+
+    unsafe {
+      device.cmd_bind_index_buffer(*command_buffer, self.index_buffer,
+                                   0, vk::IndexType::UINT32)
+    };
+
+    unsafe {
+      device.cmd_bind_descriptor_sets(*command_buffer,
+                                      vk::PipelineBindPoint::GRAPHICS,
+                                      render_state.pipeline_layout,
+                                      0,
+                                      &[*descriptor_set],
+                                      &[])
+    };
+
+    let scale = Vec3::new(1.0, 1.0, 1.0);
+    let model = Transformation {
+      rotation: Vec4::rotation_quaternion(&Vec3::new(0.0, 1.0, 0.0),
+                                          time % TAU),
+      translation: Vec3::new(0.0, 0.0, 0.0),
+    };
+    let push_block = VertexPushBlock::<f32> { scale, model };
+    let size = size_of::<VertexPushBlock::<f32>>();
+    let push_block_bytes = unsafe {
+      std::slice::from_raw_parts(&push_block as *const VertexPushBlock<f32>
+                                             as *const u8,
+                                 size)
+    };
+
+    unsafe {
+      device.cmd_push_constants(*command_buffer, render_state.pipeline_layout,
+                                vk::ShaderStageFlags::VERTEX,
+                                0,
+                                push_block_bytes)
+    };
+
+    unsafe {
+      device.cmd_draw_indexed(*command_buffer, self.index_count as u32,
+                              1, 0, 0, 0)
+    };
+  }
+}
+
+
+fn init_vertex_buffer(vertices: Vec<Vertex<f32>>, 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::VERTEX_BUFFER, &vertices)
+}
+
+
+fn init_index_buffer(indices: Vec<u32>, 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)
+}
+