summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/graphics/frame.rs227
-rw-r--r--src/graphics/mod.rs2
-rw-r--r--src/graphics/render.rs180
-rw-r--r--src/graphics/scene.rs7
-rw-r--r--src/main.rs2
5 files changed, 250 insertions, 168 deletions
diff --git a/src/graphics/frame.rs b/src/graphics/frame.rs
new file mode 100644
index 0000000..721eced
--- /dev/null
+++ b/src/graphics/frame.rs
@@ -0,0 +1,227 @@
+#![deny(unsafe_code)]
+use crate::error::*;
+use crate::graphics::{ Permanent, ForReinit, WindowDressing, Texture };
+use crate::shader_data::UniformBlock;
+
+use std::mem::size_of;
+
+use vulkanalia::Device;
+use vulkanalia::vk::{ self, HasBuilder, DeviceV1_0 };
+
+
+//   Frame is a state object that collects the Vulkan graphics objects which
+// are used as part of rendering and which need to exist in multiples, one for
+// each frame that can be rendered in parallel (see N_SIMULTANEOUS_FRAMES in
+// window_dressing.rs). As with WindowDressing, these need to be regenerated
+// or modified when the window changes.
+#[derive(Debug)]
+pub struct Frame {
+  pub framebuffer: vk::Framebuffer,
+  pub command_buffer: vk::CommandBuffer,
+  pub descriptor_set: vk::DescriptorSet,
+}
+
+
+impl Frame {
+  //   The lifecycle stuff for Frame is a little different. The Vulkan API to
+  // allocate and deallocate command buffers is designed on the assumption you
+  // want to handle a few of them simultaneously. That is in fact what we want,
+  // so the interfaces to new() and reinit() work on Vec<Frame> instead of on
+  // an indidivual Frame.
+  pub fn new(permanent: &Permanent, for_reinit: &ForReinit,
+             window_dressing: &WindowDressing, texture: &Texture,
+             render_pass: &vk::RenderPass)
+      -> Result<Vec<Self>>
+  {
+    let device = &permanent.device;
+    let primary_command_pool = &permanent.primary_command_pool;
+    let descriptor_set_layout = &for_reinit.descriptor_set_layout;
+    let swapchain = &window_dressing.swapchain;
+    let color_image_view = &window_dressing.color_image_view;
+    let depth_image_view = &window_dressing.depth_image_view;
+    let uniform_buffers = &window_dressing.uniform_buffers;
+    let descriptor_pool = &window_dressing.descriptor_pool;
+    let sampler = &window_dressing.sampler;
+
+    let count = swapchain.image_views.len();
+
+    let command_buffers = init_command_buffers(count, device,
+                                               primary_command_pool)?;
+
+    let descriptor_sets
+            = init_descriptor_sets(count, device, descriptor_set_layout,
+                                   &uniform_buffers, &descriptor_pool,
+                                   &texture.image_view, &sampler)?;
+
+    let mut frames = Vec::new();
+    for (index, color_resolve_image_view)
+        in swapchain.image_views.iter().enumerate()
+    {
+      let framebuffer = init_framebuffer(
+              device, &swapchain.extent, &color_image_view, &depth_image_view,
+              color_resolve_image_view, &render_pass)?;
+
+      frames.push(Frame {
+        command_buffer: command_buffers[index],
+        descriptor_set: descriptor_sets[index],
+        framebuffer,
+      });
+    }
+
+    Ok(frames)
+  }
+
+  // See new() in regard to the Vec.
+  pub fn reinit(frames: &mut Vec<Self>, permanent: &Permanent,
+                for_reinit: &ForReinit, window_dressing: &WindowDressing,
+                texture: &Texture, render_pass: &vk::RenderPass)
+      -> Result<()>
+  {
+    let device = &permanent.device;
+    let primary_command_pool = &permanent.primary_command_pool;
+    let descriptor_set_layout = &for_reinit.descriptor_set_layout;
+    let swapchain = &window_dressing.swapchain;
+    let color_image_view = &window_dressing.color_image_view;
+    let depth_image_view = &window_dressing.depth_image_view;
+    let uniform_buffers = &window_dressing.uniform_buffers;
+    let descriptor_pool = &window_dressing.descriptor_pool;
+    let sampler = &window_dressing.sampler;
+
+    frames.clear();
+
+    let count = swapchain.image_views.len();
+
+    // Notice that we reused the command pool.
+    let command_buffers = init_command_buffers(count, device,
+                                               primary_command_pool)?;
+
+    let descriptor_sets
+            = init_descriptor_sets(count, device, descriptor_set_layout,
+                                   &uniform_buffers, &descriptor_pool,
+                                   &texture.image_view, sampler)?;
+
+    for (index, color_resolve_image_view)
+        in swapchain.image_views.iter().enumerate()
+    {
+      let framebuffer = init_framebuffer(
+              device, &swapchain.extent, &color_image_view, &depth_image_view,
+              color_resolve_image_view, &render_pass)?;
+
+      frames.push(Frame {
+        command_buffer: command_buffers[index],
+        descriptor_set: descriptor_sets[index],
+        framebuffer,
+      });
+    }
+
+    Ok(())
+  }
+}
+
+
+#[allow(unsafe_code)]
+fn init_framebuffer(device: &Device, extent: &vk::Extent2D,
+                     color_image_view: &vk::ImageView,
+                     depth_image_view: &vk::ImageView,
+                     color_resolve_image_view: &vk::ImageView,
+                     render_pass: &vk::RenderPass)
+    -> Result<vk::Framebuffer>
+{
+  let attachments = [*color_image_view,
+                     *depth_image_view,
+                     *color_resolve_image_view];
+
+  let framebuffer_info = vk::FramebufferCreateInfo::builder()
+          .render_pass(*render_pass)
+          .attachments(&attachments)
+          .width(extent.width)
+          .height(extent.height)
+          .layers(1);
+
+  let framebuffer = unsafe {
+    device.create_framebuffer(&framebuffer_info, None)
+  }?;
+
+  Ok(framebuffer)
+}
+
+
+#[allow(unsafe_code)]
+fn init_command_buffers(count: usize, device: &Device,
+                        command_pool: &vk::CommandPool)
+    -> Result<Vec<vk::CommandBuffer>>
+{
+  let command_buffer_allocation_info
+          = vk::CommandBufferAllocateInfo::builder()
+                .command_pool(*command_pool)
+                .level(vk::CommandBufferLevel::PRIMARY)
+                .command_buffer_count(count as u32);
+  let command_buffers = unsafe {
+    device.allocate_command_buffers(&command_buffer_allocation_info)
+  }?;
+
+  Ok(command_buffers)
+}
+
+
+#[allow(unsafe_code)]
+fn init_descriptor_sets(count: usize, device: &Device,
+                        layout: &vk::DescriptorSetLayout,
+                        buffers: &Vec<vk::Buffer>, pool: &vk::DescriptorPool,
+                        texture_image_view: &vk::ImageView,
+                        sampler: &vk::Sampler)
+    -> Result<Vec<vk::DescriptorSet>>
+{
+  let layouts = vec![*layout; count];
+  let set_info = vk::DescriptorSetAllocateInfo::builder()
+          .descriptor_pool(*pool)
+          .set_layouts(&layouts);
+  let sets = unsafe { device.allocate_descriptor_sets(&set_info) }?;
+
+  for index in 0 .. count {
+    let buffer_info = vk::DescriptorBufferInfo::builder()
+            .buffer(buffers[index])
+            .offset(0)
+            .range(size_of::<UniformBlock<f32>>() as vk::DeviceSize);
+
+    let buffer_info_list = [buffer_info];
+    let uniform_block_write_info = vk::WriteDescriptorSet::builder()
+            .dst_set(sets[index])
+            .dst_binding(0)
+            .dst_array_element(0)
+            .descriptor_type(vk::DescriptorType::UNIFORM_BUFFER)
+            .buffer_info(&buffer_info_list);
+
+    let sampler_image_info = vk::DescriptorImageInfo::builder()
+            .sampler(*sampler);
+    let sampler_image_info_list = [sampler_image_info];
+    let sampler_write_info = vk::WriteDescriptorSet::builder()
+            .dst_set(sets[index])
+            .dst_binding(1)
+            .dst_array_element(0)
+            .descriptor_type(vk::DescriptorType::SAMPLER)
+            .image_info(&sampler_image_info_list);
+
+    let texture_image_info = vk::DescriptorImageInfo::builder()
+            .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
+            .image_view(*texture_image_view);
+    let texture_image_info_list = [texture_image_info];
+    let texture_write_info = vk::WriteDescriptorSet::builder()
+            .dst_set(sets[index])
+            .dst_binding(2)
+            .dst_array_element(0)
+            .descriptor_type(vk::DescriptorType::SAMPLED_IMAGE)
+            .image_info(&texture_image_info_list);
+
+    let write_info_list = [
+            uniform_block_write_info, sampler_write_info, texture_write_info
+    ];
+    let copy_info_list: [vk::CopyDescriptorSet; 0] = [];
+
+    unsafe {
+      device.update_descriptor_sets(&write_info_list, &copy_info_list)
+    };
+  }
+
+  Ok(sets)
+}
diff --git a/src/graphics/mod.rs b/src/graphics/mod.rs
index bb12c80..7b46cb1 100644
--- a/src/graphics/mod.rs
+++ b/src/graphics/mod.rs
@@ -1,4 +1,5 @@
 #![deny(unsafe_code)]
+pub mod frame;
 pub mod model;
 pub mod permanent;
 pub mod render;
@@ -7,6 +8,7 @@ pub mod scene;
 pub mod util;
 pub mod window_dressing;
 
+pub use crate::graphics::frame::Frame;
 pub use crate::graphics::model::Model;
 pub use crate::graphics::texture::Texture;
 pub use crate::graphics::permanent::{ Permanent, ForReinit };
diff --git a/src/graphics/render.rs b/src/graphics/render.rs
index c88b1d6..00e55ee 100644
--- a/src/graphics/render.rs
+++ b/src/graphics/render.rs
@@ -1,8 +1,10 @@
 #![deny(unsafe_code)]
 use crate::error::*;
 use crate::assets::asset;
-use crate::graphics::{ Permanent, ForReinit, WindowDressing, Model, Texture };
-use crate::shader_data::{ Vertex, UniformBlock, VertexPushBlock };
+use crate::graphics::{
+  Permanent, ForReinit, WindowDressing, Frame, Model, Texture
+};
+use crate::shader_data::{ Vertex, VertexPushBlock };
 
 use std::mem::size_of;
 
@@ -22,9 +24,7 @@ pub struct Render {
 
   pub model: Option<Model>,
 
-  pub framebuffers: Vec<vk::Framebuffer>,
-  pub command_buffers: Vec<vk::CommandBuffer>,
-  pub descriptor_sets: Vec<vk::DescriptorSet>,
+  pub per_frame: Vec<Frame>,
 }
 
 
@@ -34,16 +34,10 @@ impl Render {
       -> Result<Self>
   {
     let device = &permanent.device;
-    let primary_command_pool = &permanent.primary_command_pool;
     let sample_count = for_reinit.sample_count;
     let descriptor_set_layout = &for_reinit.descriptor_set_layout;
     let swapchain = &window_dressing.swapchain;
     let depth_format = &window_dressing.depth_format;
-    let color_image_view = &window_dressing.color_image_view;
-    let depth_image_view = &window_dressing.depth_image_view;
-    let uniform_buffers = &window_dressing.uniform_buffers;
-    let descriptor_pool = &window_dressing.descriptor_pool;
-    let sampler = &window_dressing.sampler;
 
     let render_pass = init_render_pass(device, sample_count,
                                        &swapchain.format, &depth_format)?;
@@ -52,18 +46,8 @@ impl Render {
             = init_pipeline(device, descriptor_set_layout, &swapchain.extent,
                             sample_count, &render_pass)?;
 
-    let framebuffers = init_framebuffers(
-            device, &swapchain.extent, &swapchain.image_views,
-            &color_image_view, &depth_image_view, &render_pass)?;
-
-    let command_buffers = init_command_buffers(device, &framebuffers,
-                                               primary_command_pool)?;
-
-    let descriptor_sets
-            = init_descriptor_sets(device, descriptor_set_layout,
-                                   &uniform_buffers, &descriptor_pool,
-                                   swapchain.images.len(),
-                                   &texture.image_view, &sampler)?;
+    let per_frame = Frame::new(permanent, for_reinit, window_dressing,
+                               texture, &render_pass)?;
 
     let model = None;
 
@@ -72,9 +56,7 @@ impl Render {
       pipeline,
       pipeline_layout,
       model,
-      framebuffers,
-      command_buffers,
-      descriptor_sets,
+      per_frame,
     })
   }
 
@@ -88,16 +70,10 @@ impl Render {
     self.destroy_replaceable(permanent);
 
     let device = &permanent.device;
-    let primary_command_pool = &permanent.primary_command_pool;
     let sample_count = for_reinit.sample_count;
     let descriptor_set_layout = &for_reinit.descriptor_set_layout;
     let swapchain = &window_dressing.swapchain;
     let depth_format = &window_dressing.depth_format;
-    let color_image_view = &window_dressing.color_image_view;
-    let depth_image_view = &window_dressing.depth_image_view;
-    let uniform_buffers = &window_dressing.uniform_buffers;
-    let descriptor_pool = &window_dressing.descriptor_pool;
-    let sampler = &window_dressing.sampler;
 
     let render_pass = init_render_pass(device, sample_count,
                                        &swapchain.format, &depth_format)?;
@@ -106,26 +82,12 @@ impl Render {
             = init_pipeline(device, descriptor_set_layout, &swapchain.extent,
                             sample_count, &render_pass)?;
 
-    let framebuffers = init_framebuffers(
-            device, &swapchain.extent, &swapchain.image_views,
-            &color_image_view, &depth_image_view, &render_pass)?;
-
-    // Notice that we reused the command pool.
-    let command_buffers = init_command_buffers(device, &framebuffers,
-                                               primary_command_pool)?;
-
-    let descriptor_sets
-            = init_descriptor_sets(device, descriptor_set_layout,
-                                   &uniform_buffers, &descriptor_pool,
-                                   swapchain.images.len(),
-                                   &texture.image_view, sampler)?;
+    Frame::reinit(&mut self.per_frame, permanent, for_reinit, window_dressing,
+                  texture, &render_pass)?;
 
     self.render_pass = render_pass;
     self.pipeline = pipeline;
     self.pipeline_layout = pipeline_layout;
-    self.framebuffers = framebuffers;
-    self.command_buffers = command_buffers;
-    self.descriptor_sets = descriptor_sets;
 
     Ok(())
   }
@@ -145,8 +107,11 @@ impl Render {
   fn destroy_replaceable(&mut self, permanent: &Permanent) {
     let device = &permanent.device;
 
-    for framebuffer in &self.framebuffers {
-      unsafe { device.destroy_framebuffer(*framebuffer, None) };
+    let mut command_buffers = Vec::new();
+    for frame in &self.per_frame {
+      unsafe { device.destroy_framebuffer(frame.framebuffer, None) };
+
+      command_buffers.push(frame.command_buffer);
     }
 
     //   Notice that we free the buffers in the pool, but do not destroy the
@@ -156,7 +121,7 @@ impl Render {
     // immediately after using them.
     unsafe {
       device.free_command_buffers(permanent.primary_command_pool,
-                                  &self.command_buffers)
+                                  &command_buffers)
     };
 
     unsafe { device.destroy_pipeline(self.pipeline, None) };
@@ -392,116 +357,3 @@ fn init_pipeline(device: &Device,
   Ok((pipeline_layout, pipeline))
 }
 
-
-#[allow(unsafe_code)]
-fn init_framebuffers(device: &Device, extent: &vk::Extent2D,
-                     swapchain_image_views: &Vec<vk::ImageView>,
-                     color_image_view: &vk::ImageView,
-                     depth_image_view: &vk::ImageView,
-                     render_pass: &vk::RenderPass)
-    -> Result<Vec<vk::Framebuffer>>
-{
-  let mut framebuffers = Vec::new();
-
-  for color_resolve_image_view in swapchain_image_views {
-    let attachments = [*color_image_view,
-                       *depth_image_view,
-                       *color_resolve_image_view];
-
-    let framebuffer_info = vk::FramebufferCreateInfo::builder()
-            .render_pass(*render_pass)
-            .attachments(&attachments)
-            .width(extent.width)
-            .height(extent.height)
-            .layers(1);
-
-    let framebuffer = unsafe {
-      device.create_framebuffer(&framebuffer_info, None)
-    }?;
-
-    framebuffers.push(framebuffer);
-  }
-
-  Ok(framebuffers)
-}
-
-
-#[allow(unsafe_code)]
-fn init_command_buffers(device: &Device,
-                        framebuffers: &Vec<vk::Framebuffer>,
-                        command_pool: &vk::CommandPool)
-    -> Result<Vec<vk::CommandBuffer>>
-{
-  let command_buffer_allocation_info
-          = vk::CommandBufferAllocateInfo::builder()
-                .command_pool(*command_pool)
-                .level(vk::CommandBufferLevel::PRIMARY)
-                .command_buffer_count(framebuffers.len() as u32);
-  let command_buffers = unsafe {
-    device.allocate_command_buffers(&command_buffer_allocation_info)
-  }?;
-
-  Ok(command_buffers)
-}
-
-
-#[allow(unsafe_code)]
-fn init_descriptor_sets(device: &Device, layout: &vk::DescriptorSetLayout,
-                        buffers: &Vec<vk::Buffer>, pool: &vk::DescriptorPool,
-                        count: usize, texture_image_view: &vk::ImageView,
-                        sampler: &vk::Sampler)
-    -> Result<Vec<vk::DescriptorSet>>
-{
-  let layouts = vec![*layout; count];
-  let set_info = vk::DescriptorSetAllocateInfo::builder()
-          .descriptor_pool(*pool)
-          .set_layouts(&layouts);
-  let sets = unsafe { device.allocate_descriptor_sets(&set_info) }?;
-
-  for index in 0 .. count {
-    let buffer_info = vk::DescriptorBufferInfo::builder()
-            .buffer(buffers[index])
-            .offset(0)
-            .range(size_of::<UniformBlock<f32>>() as vk::DeviceSize);
-
-    let buffer_info_list = [buffer_info];
-    let uniform_block_write_info = vk::WriteDescriptorSet::builder()
-            .dst_set(sets[index])
-            .dst_binding(0)
-            .dst_array_element(0)
-            .descriptor_type(vk::DescriptorType::UNIFORM_BUFFER)
-            .buffer_info(&buffer_info_list);
-
-    let sampler_image_info = vk::DescriptorImageInfo::builder()
-            .sampler(*sampler);
-    let sampler_image_info_list = [sampler_image_info];
-    let sampler_write_info = vk::WriteDescriptorSet::builder()
-            .dst_set(sets[index])
-            .dst_binding(1)
-            .dst_array_element(0)
-            .descriptor_type(vk::DescriptorType::SAMPLER)
-            .image_info(&sampler_image_info_list);
-
-    let texture_image_info = vk::DescriptorImageInfo::builder()
-            .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
-            .image_view(*texture_image_view);
-    let texture_image_info_list = [texture_image_info];
-    let texture_write_info = vk::WriteDescriptorSet::builder()
-            .dst_set(sets[index])
-            .dst_binding(2)
-            .dst_array_element(0)
-            .descriptor_type(vk::DescriptorType::SAMPLED_IMAGE)
-            .image_info(&texture_image_info_list);
-
-    let write_info_list = [
-            uniform_block_write_info, sampler_write_info, texture_write_info
-    ];
-    let copy_info_list: [vk::CopyDescriptorSet; 0] = [];
-
-    unsafe {
-      device.update_descriptor_sets(&write_info_list, &copy_info_list)
-    };
-  }
-
-  Ok(sets)
-}
diff --git a/src/graphics/scene.rs b/src/graphics/scene.rs
index 874e9ea..f73ebf2 100644
--- a/src/graphics/scene.rs
+++ b/src/graphics/scene.rs
@@ -12,9 +12,10 @@ pub fn generate_scene_commands<'a>(image_index: usize, time: f32,
                                    device: &Device, extent: &vk::Extent2D)
     -> Result<&'a vk::CommandBuffer>
 {
-  let command_buffer = &render.command_buffers[image_index];
-  let framebuffer = &render.framebuffers[image_index];
-  let descriptor_set = &render.descriptor_sets[image_index];
+  let frame = &render.per_frame[image_index];
+  let command_buffer = &frame.command_buffer;
+  let framebuffer = &frame.framebuffer;
+  let descriptor_set = &frame.descriptor_set;
 
   let inheritance_info = vk::CommandBufferInheritanceInfo::builder();
 
diff --git a/src/main.rs b/src/main.rs
index 607b0d8..b5af438 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,7 @@
 #![deny(unsafe_code)]
 use crate::error::*;
 use crate::assets::asset;
-use crate::graphics::{ Permanent, ForReinit, Render, Model, Texture };
+use crate::graphics::{ Permanent, ForReinit, Render, Texture };
 use crate::graphics::scene::generate_scene_commands;
 use crate::graphics::window_dressing::{
   WindowDressing, N_SIMULTANEOUS_FRAMES