summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/graphics_scene.rs121
-rw-r--r--src/graphics_window_dressing.rs135
-rw-r--r--src/main.rs38
-rw-r--r--src/shader_data.rs9
4 files changed, 184 insertions, 119 deletions
diff --git a/src/graphics_scene.rs b/src/graphics_scene.rs
new file mode 100644
index 0000000..771255a
--- /dev/null
+++ b/src/graphics_scene.rs
@@ -0,0 +1,121 @@
+#![deny(unsafe_code)]
+use crate::error::*;
+use crate::linear_algebra::{ Vec3, Vec4, Transformation };
+use crate::shader_data::VertexPushBlock;
+
+use std::f32::consts::{ TAU };
+use std::mem::size_of;
+
+use vulkanalia::Device;
+use vulkanalia::vk::{ self, HasBuilder, DeviceV1_0 };
+
+
+#[allow(unsafe_code)]
+pub fn generate_scene_commands(command_buffer: &vk::CommandBuffer,
+                               time: f32, device: &Device,
+                               extent: &vk::Extent2D,
+                               framebuffer: &vk::Framebuffer,
+                               render_pass: &vk::RenderPass,
+                               pipeline_layout: &vk::PipelineLayout,
+                               pipeline: &vk::Pipeline,
+                               vertex_buffer: &vk::Buffer,
+                               index_buffer: &vk::Buffer,
+                               index_count: usize,
+                               descriptor_set: &vk::DescriptorSet)
+    -> Result<()>
+{
+  let inheritance_info = vk::CommandBufferInheritanceInfo::builder();
+
+  let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder()
+          .flags(vk::CommandBufferUsageFlags::empty())
+          .inheritance_info(&inheritance_info);
+
+  unsafe {
+    device.begin_command_buffer(*command_buffer, &command_buffer_begin_info)
+  }?;
+
+  let render_area = vk::Rect2D::builder()
+          .offset(vk::Offset2D::default())
+          .extent(*extent);
+
+  let color_clear_value = vk::ClearValue {
+    color: vk::ClearColorValue {
+      float32: [0.0, 0.0, 0.0, 1.0]
+    }
+  };
+  let depth_clear_value = vk::ClearValue {
+    depth_stencil: vk::ClearDepthStencilValue {
+      depth: 1.0,
+      stencil: 0,
+    }
+  };
+  let clear_values = [color_clear_value, depth_clear_value];
+
+  let begin_pass_info = vk::RenderPassBeginInfo::builder()
+          .render_pass(*render_pass)
+          .framebuffer(*framebuffer)
+          .render_area(render_area)
+          .clear_values(&clear_values);
+
+  unsafe {
+    device.cmd_begin_render_pass(*command_buffer, &begin_pass_info,
+                                 vk::SubpassContents::INLINE)
+  };
+
+  unsafe {
+    device.cmd_bind_pipeline(*command_buffer,
+                             vk::PipelineBindPoint::GRAPHICS,
+                             *pipeline)
+  };
+
+  unsafe {
+    device.cmd_bind_vertex_buffers(*command_buffer, 0,
+                                   &[*vertex_buffer], &[0])
+  };
+
+  unsafe {
+    device.cmd_bind_index_buffer(*command_buffer, *index_buffer, 0,
+                                 vk::IndexType::UINT32)
+  };
+
+  unsafe {
+    device.cmd_bind_descriptor_sets(*command_buffer,
+                                    vk::PipelineBindPoint::GRAPHICS,
+                                    *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, *pipeline_layout,
+                              vk::ShaderStageFlags::VERTEX,
+                              0,
+                              push_block_bytes)
+  };
+
+  unsafe {
+    device.cmd_draw_indexed(*command_buffer, index_count as u32,
+                            1, 0, 0, 0)
+  };
+
+  unsafe { device.cmd_end_render_pass(*command_buffer) };
+
+  unsafe { device.end_command_buffer(*command_buffer) }?;
+
+  Ok(())
+}
+
diff --git a/src/graphics_window_dressing.rs b/src/graphics_window_dressing.rs
index 3c9291c..51483cf 100644
--- a/src/graphics_window_dressing.rs
+++ b/src/graphics_window_dressing.rs
@@ -5,10 +5,11 @@ use crate::graphics_permanent::{
   EnableAnisotropy
 };
 use crate::model_loader::load_model;
-use crate::shader_data::{ Vertex, UniformBlock };
+use crate::shader_data::{ Vertex, UniformBlock, VertexPushBlock };
 
 use std::collections::BTreeSet;
 use std::io::Cursor;
+use std::mem::size_of;
 use std::ptr::copy_nonoverlapping;
 
 use png::Decoder;
@@ -41,22 +42,22 @@ pub struct WindowDressing {
   depth_image_view: vk::ImageView,
   depth_format: vk::Format,
 
-  render_pass: vk::RenderPass,
+  pub render_pass: vk::RenderPass,
 
-  pipeline: vk::Pipeline,
-  pipeline_layout: vk::PipelineLayout,
+  pub pipeline: vk::Pipeline,
+  pub pipeline_layout: vk::PipelineLayout,
 
-  framebuffers: Vec<vk::Framebuffer>,
+  pub framebuffers: Vec<vk::Framebuffer>,
 
   primary_command_pool: vk::CommandPool,
   transient_command_pool: vk::CommandPool,
 
-  vertex_buffer: vk::Buffer,
+  pub vertex_buffer: vk::Buffer,
   vertex_buffer_memory: vk::DeviceMemory,
 
-  index_buffer: vk::Buffer,
+  pub index_buffer: vk::Buffer,
   index_buffer_memory: vk::DeviceMemory,
-  index_count: usize,
+  pub index_count: usize,
 
   texture_image: vk::Image,
   texture_image_memory: vk::DeviceMemory,
@@ -68,7 +69,7 @@ pub struct WindowDressing {
   pub uniform_buffer_memory: Vec<vk::DeviceMemory>,
 
   descriptor_pool: vk::DescriptorPool,
-  descriptor_sets: Vec<vk::DescriptorSet>,
+  pub descriptor_sets: Vec<vk::DescriptorSet>,
 
   pub command_buffers: Vec<vk::CommandBuffer>,
 
@@ -179,7 +180,7 @@ impl WindowDressing {
                                    swapchain.images.len(),
                                    &texture_image_view, &sampler)?;
 
-    let command_buffers = init_commands(
+    let command_buffers = init_command_buffers(
             device, &swapchain.extent, &framebuffers, &render_pass,
             &pipeline_layout, &pipeline, &vertex_buffer, &index_buffer,
             index_count, &descriptor_sets, &primary_command_pool)?;
@@ -276,7 +277,7 @@ impl WindowDressing {
                                    &self.texture_image_view, &self.sampler)?;
 
     // Notice that we reused the command pool.
-    let command_buffers = init_commands(
+    let command_buffers = init_command_buffers(
             device, &swapchain.extent, &framebuffers, &render_pass,
             &pipeline_layout, &pipeline, &self.vertex_buffer,
             &self.index_buffer, self.index_count, &descriptor_sets,
@@ -696,9 +697,16 @@ fn init_pipeline(device: &Device,
           .attachments(&blend_attachments)
           .blend_constants([0.0, 0.0, 0.0, 0.0]);
 
+  let vertex_push_constant_range = vk::PushConstantRange::builder()
+          .stage_flags(vk::ShaderStageFlags::VERTEX)
+          .offset(0)
+          .size(size_of::<VertexPushBlock<f32>>() as u32);
+
   let layouts = [*descriptor_set_layout];
+  let push_constant_ranges = [vertex_push_constant_range];
   let pipeline_layout_info = vk::PipelineLayoutCreateInfo::builder()
-                                 .set_layouts(&layouts);
+                                 .set_layouts(&layouts)
+                                 .push_constant_ranges(&push_constant_ranges);
 
   let pipeline_layout = unsafe {
     device.create_pipeline_layout(&pipeline_layout_info, None)
@@ -1014,8 +1022,9 @@ fn init_command_pools(device: &Device, indices: &QueueFamilyIndices)
     -> Result<(vk::CommandPool, vk::CommandPool)>
 {
   let command_pool_info = vk::CommandPoolCreateInfo::builder()
-                              .flags(vk::CommandPoolCreateFlags::empty())
-                              .queue_family_index(indices.graphics);
+          .flags(vk::CommandPoolCreateFlags::TRANSIENT
+                 | vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER)
+          .queue_family_index(indices.graphics);
 
   let primary = unsafe {
     device.create_command_pool(&command_pool_info, None)
@@ -1031,17 +1040,17 @@ fn init_command_pools(device: &Device, indices: &QueueFamilyIndices)
 
 
 #[allow(unsafe_code)]
-fn init_commands(device: &Device,
-                 extent: &vk::Extent2D,
-                 framebuffers: &Vec<vk::Framebuffer>,
-                 render_pass: &vk::RenderPass,
-                 pipeline_layout: &vk::PipelineLayout,
-                 pipeline: &vk::Pipeline,
-                 vertex_buffer: &vk::Buffer,
-                 index_buffer: &vk::Buffer,
-                 index_count: usize,
-                 descriptor_sets: &Vec<vk::DescriptorSet>,
-                 command_pool: &vk::CommandPool)
+fn init_command_buffers(device: &Device,
+                        extent: &vk::Extent2D,
+                        framebuffers: &Vec<vk::Framebuffer>,
+                        render_pass: &vk::RenderPass,
+                        pipeline_layout: &vk::PipelineLayout,
+                        pipeline: &vk::Pipeline,
+                        vertex_buffer: &vk::Buffer,
+                        index_buffer: &vk::Buffer,
+                        index_count: usize,
+                        descriptor_sets: &Vec<vk::DescriptorSet>,
+                        command_pool: &vk::CommandPool)
     -> Result<Vec<vk::CommandBuffer>>
 {
   let command_buffer_allocation_info
@@ -1053,82 +1062,6 @@ fn init_commands(device: &Device,
     device.allocate_command_buffers(&command_buffer_allocation_info)
   }?;
 
-  for (index, framebuffer) in framebuffers.iter().enumerate() {
-    let command_buffer = command_buffers[index];
-
-    let inheritance_info = vk::CommandBufferInheritanceInfo::builder();
-
-    let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder()
-            .flags(vk::CommandBufferUsageFlags::empty())
-            .inheritance_info(&inheritance_info);
-
-    unsafe {
-      device.begin_command_buffer(command_buffer, &command_buffer_begin_info)
-    }?;
-
-    let render_area = vk::Rect2D::builder()
-            .offset(vk::Offset2D::default())
-            .extent(*extent);
-
-    let color_clear_value = vk::ClearValue {
-      color: vk::ClearColorValue {
-        float32: [0.0, 0.0, 0.0, 1.0]
-      }
-    };
-    let depth_clear_value = vk::ClearValue {
-      depth_stencil: vk::ClearDepthStencilValue {
-        depth: 1.0,
-        stencil: 0,
-      }
-    };
-    let clear_values = [color_clear_value, depth_clear_value];
-
-    let begin_pass_info = vk::RenderPassBeginInfo::builder()
-            .render_pass(*render_pass)
-            .framebuffer(*framebuffer)
-            .render_area(render_area)
-            .clear_values(&clear_values);
-
-    unsafe {
-      device.cmd_begin_render_pass(command_buffer, &begin_pass_info,
-                                   vk::SubpassContents::INLINE)
-    };
-
-    unsafe {
-      device.cmd_bind_pipeline(command_buffer,
-                               vk::PipelineBindPoint::GRAPHICS,
-                               *pipeline)
-    };
-
-    unsafe {
-      device.cmd_bind_vertex_buffers(command_buffer, 0,
-                                     &[*vertex_buffer], &[0])
-    };
-
-    unsafe {
-      device.cmd_bind_index_buffer(command_buffer, *index_buffer, 0,
-                                   vk::IndexType::UINT32)
-    };
-
-    unsafe {
-      device.cmd_bind_descriptor_sets(command_buffer,
-                                      vk::PipelineBindPoint::GRAPHICS,
-                                      *pipeline_layout,
-                                      0,
-                                      &[descriptor_sets[index]],
-                                      &[])
-    };
-
-    unsafe {
-      device.cmd_draw_indexed(command_buffer, index_count as u32,
-                              1, 0, 0, 0)
-    };
-
-    unsafe { device.cmd_end_render_pass(command_buffer) };
-
-    unsafe { device.end_command_buffer(command_buffer) }?;
-  }
-
   Ok(command_buffers)
 }
 
diff --git a/src/main.rs b/src/main.rs
index 3267d0b..8a42147 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,11 +6,11 @@ use crate::graphics_permanent::{
 use crate::graphics_window_dressing::{
   WindowDressing, N_SIMULTANEOUS_FRAMES
 };
-use crate::linear_algebra::{ Vec3, Vec4, Mat4, Transformation };
+use crate::linear_algebra::{ Vec3, Mat4, Transformation };
 use crate::shader_data::UniformBlock;
 
 use std::cell::RefCell;
-use std::f32::consts::{ FRAC_PI_4, TAU };
+use std::f32::consts::FRAC_PI_4;
 use std::ptr::copy_nonoverlapping;
 use std::time::Instant;
 use vulkanalia::Device;
@@ -23,6 +23,7 @@ use winit::window::WindowId;
 
 mod error;
 mod graphics_permanent;
+mod graphics_scene;
 mod graphics_window_dressing;
 mod linear_algebra;
 mod model_loader;
@@ -138,16 +139,28 @@ impl Surreality {
 
       concurrency.image_fences[image_index] = *frame_fence;
 
-      render_uniforms(device,
+      let time = self.simulation_start.elapsed().as_secs_f32();
+
+      let command_buffer = window_dressing.command_buffers[image_index];
+      let framebuffer = window_dressing.framebuffers[image_index];
+      let descriptor_set = window_dressing.descriptor_sets[image_index];
+
+      crate::graphics_scene::generate_scene_commands(
+          &command_buffer, time, device, &window_dressing.swapchain.extent,
+          &framebuffer, &window_dressing.render_pass,
+          &window_dressing.pipeline_layout, &window_dressing.pipeline,
+          &window_dressing.vertex_buffer, &window_dressing.index_buffer,
+          window_dressing.index_count, &descriptor_set)?;
+
+      render_uniforms(time, device,
                       &window_dressing.uniform_buffer_memory[image_index],
-                      &window_dressing.swapchain.extent,
-                      self.simulation_start)?;
+                      &window_dressing.swapchain.extent)?;
 
       let first_semaphores = [*image_available_semaphore];
       let second_semaphores = [*rendering_finished_semaphore];
 
       let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
-      let command_buffers = [window_dressing.command_buffers[image_index]];
+      let command_buffers = [command_buffer];
       let submit_info = vk::SubmitInfo::builder()
                             .wait_semaphores(&first_semaphores)
                             .wait_dst_stage_mask(&wait_stages)
@@ -282,23 +295,16 @@ fn main() -> std::process::ExitCode {
 
 
 #[allow(unsafe_code)]
-fn render_uniforms(device: &Device, device_memory: &vk::DeviceMemory,
-                   extent: &vk::Extent2D, simulation_start: Instant)
+fn render_uniforms(time: f32, device: &Device,
+                   device_memory: &vk::DeviceMemory, extent: &vk::Extent2D)
     -> Result<()>
 {
-  let time = simulation_start.elapsed().as_secs_f32();
-
-  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 view = Transformation::look_at(&Vec3::new(0.0, -3.0, -10.0),
                                      &Vec3::new(0.0, -1.0, 0.0),
                                      &Vec3::new(0.0, -1.0, 0.0));
   let aspect_ratio = extent.width as f32 / extent.height as f32;
   let projection = Mat4::perspective(FRAC_PI_4, aspect_ratio, 0.1, 100.0);
-  let block = UniformBlock::<f32> { scale, model, view, projection };
+  let block = UniformBlock::<f32> { view, projection };
 
   let size = size_of::<UniformBlock<f32>>() as u64;
   let host_memory = unsafe {
diff --git a/src/shader_data.rs b/src/shader_data.rs
index 8197bfc..892260d 100644
--- a/src/shader_data.rs
+++ b/src/shader_data.rs
@@ -16,12 +16,17 @@ pub struct Vertex<T: Copy> {
 #[repr(C)]
 #[derive(Clone, Debug)]
 pub struct UniformBlock<T: Copy> {
-  pub scale: Vec3<T>,
-  pub model: Transformation<T>,
   pub view: Transformation<T>,
   pub projection: Mat4<T>,
 }
 
+#[repr(C)]
+#[derive(Clone, Debug)]
+pub struct VertexPushBlock<T: Copy> {
+  pub scale: Vec3<T>,
+  pub model: Transformation<T>,
+}
+
 impl<T: Copy> Vertex<T> {
   pub const fn new(position: Vec3<T>, color: Vec3<T>,
                    texture_coordinates: Vec2<T>)