summary refs log tree commit diff
path: root/src/graphics_window_dressing.rs
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-07-09 15:42:47 -0700
committerIrene Knapp <ireneista@irenes.space>2026-07-09 15:42:47 -0700
commit05982c6344ec308bcd60fae9457979a20ff18bc8 (patch)
tree55a21c3717f1ef540ddf36e968e49ce7e9d52a57 /src/graphics_window_dressing.rs
parentdaac5191461ed84d41920ea9c80addb8dea977c2 (diff)
make most of the associated functions into file-level functions
now that the two halves of the graphics state are in their own files, this is easier to read

the public functions remain as part of the impl

Force-Push: yes
Change-Id: Ic7d73be04f31b484348bbc5d62cc93f0c877717c
Diffstat (limited to 'src/graphics_window_dressing.rs')
-rw-r--r--src/graphics_window_dressing.rs838
1 files changed, 424 insertions, 414 deletions
diff --git a/src/graphics_window_dressing.rs b/src/graphics_window_dressing.rs
index 6ffab41..e35332f 100644
--- a/src/graphics_window_dressing.rs
+++ b/src/graphics_window_dressing.rs
@@ -82,22 +82,22 @@ impl WindowDressing {
     let surface = &permanent.surface;
     let device = &permanent.device;
 
-    let swapchain = Self::init_swapchain(
+    let swapchain = init_swapchain(
             window, instance, surface, &physical_device, device, &indices)?;
 
-    let render_pass = Self::init_render_pass(device, &swapchain.format)?;
+    let render_pass = init_render_pass(device, &swapchain.format)?;
 
     let (pipeline_layout, pipeline)
-            = Self::init_pipeline(device, &swapchain.extent, &render_pass)?;
+            = init_pipeline(device, &swapchain.extent, &render_pass)?;
 
-    let framebuffers = Self::init_framebuffers(
+    let framebuffers = init_framebuffers(
             device, &swapchain.extent, &swapchain.image_views, &render_pass)?;
 
     let (command_pool, command_buffers)
-            = Self::init_commands(device, &swapchain.extent, &framebuffers,
-                                  &render_pass, &pipeline, &indices)?;
+            = init_commands(device, &swapchain.extent, &framebuffers,
+                            &render_pass, &pipeline, &indices)?;
 
-    let concurrency = Self::init_concurrency(device, &swapchain.images)?;
+    let concurrency = init_concurrency(device, &swapchain.images)?;
 
     Ok(WindowDressing {
       swapchain,
@@ -143,462 +143,472 @@ impl WindowDressing {
 
     unsafe { device.destroy_swapchain_khr(self.swapchain.swapchain, None) };
   }
+}
 
-  #[allow(unsafe_code)]
-  fn init_swapchain(window: &Window, instance: &Instance,
-                    surface: &vk::SurfaceKHR,
-                    physical_device: &vk::PhysicalDevice, device: &Device,
-                    indices: &QueueFamilyIndices)
-      -> Result<Swapchain>
-  {
-    let (capabilities, formats, presentation_modes)
-            = PermanentGraphicsState::find_device_swapchain_features(
-                  instance, surface, physical_device)?.require()?;
-
-    let format = Self::pick_surface_format(&formats)?;
-
-    let presentation_mode
-            = Self::pick_presentation_mode(&presentation_modes)?;
-    let extent = Self::pick_image_extent(window, capabilities)?;
-
-    let mut image_count = capabilities.min_image_count + 1;
-    if capabilities.max_image_count != 0 {
-      image_count
-          = image_count.clamp(0, capabilities.max_image_count);
-    }
-
-    let mut unique_queue_family_indices = BTreeSet::new();
-    unique_queue_family_indices.insert(indices.graphics);
-    unique_queue_family_indices.insert(indices.presentation);
-
-    //   If there's only one queue, we use exclusive sharing mode, which
-    // will allow things to work without locks. Otherwise we use concurrent
-    // mode.
-    let (ordered_indices, sharing_mode)
-            = if unique_queue_family_indices.len() < 2
-    {
-      (vec![indices.graphics], vk::SharingMode::EXCLUSIVE)
-    } else {
-      (vec![indices.graphics, indices.presentation],
-       vk::SharingMode::CONCURRENT)
-    };
 
-    let swapchain_info = vk::SwapchainCreateInfoKHR::builder()
-            .surface(*surface)
-            .min_image_count(image_count)
-            .image_format(format.format)
-            .image_color_space(format.color_space)
-            .image_extent(extent)
-            .image_array_layers(1)
-            .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
-            .image_sharing_mode(sharing_mode)
-            .queue_family_indices(&ordered_indices)
-            .pre_transform(capabilities.current_transform)
-            .composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
-            .present_mode(presentation_mode)
-            .clipped(true)
-            .old_swapchain(vk::SwapchainKHR::null());
-
-    let swapchain = unsafe {
-      device.create_swapchain_khr(&swapchain_info, None)
-    }?;
+#[allow(unsafe_code)]
+fn init_swapchain(window: &Window, instance: &Instance,
+                  surface: &vk::SurfaceKHR,
+                  physical_device: &vk::PhysicalDevice, device: &Device,
+                  indices: &QueueFamilyIndices)
+    -> Result<Swapchain>
+{
+  let (capabilities, formats, presentation_modes)
+          = PermanentGraphicsState::find_device_swapchain_features(
+                instance, surface, physical_device)?.require()?;
 
-    let images = unsafe {
-      device.get_swapchain_images_khr(swapchain)
-    }?;
+  let format = pick_surface_format(&formats)?;
 
-    let mut image_views = Vec::new();
-    for image in &images {
-      let components = vk::ComponentMapping::builder()
-                           .r(vk::ComponentSwizzle::IDENTITY)
-                           .g(vk::ComponentSwizzle::IDENTITY)
-                           .b(vk::ComponentSwizzle::IDENTITY)
-                           .a(vk::ComponentSwizzle::IDENTITY);
-
-      let subresource_range = vk::ImageSubresourceRange::builder()
-                                  .aspect_mask(vk::ImageAspectFlags::COLOR)
-                                  .base_mip_level(0)
-                                  .level_count(1)
-                                  .base_array_layer(0)
-                                  .layer_count(1);
-
-      let view_info = vk::ImageViewCreateInfo::builder()
-                          .image(*image)
-                          .view_type(vk::ImageViewType::_2D)
-                          .format(format.format)
-                          .components(components)
-                          .subresource_range(subresource_range);
-
-      let view = unsafe {
-        device.create_image_view(&view_info, None)
-      }?;
-
-      image_views.push(view);
-    }
+  let presentation_mode
+          = pick_presentation_mode(&presentation_modes)?;
+  let extent = pick_image_extent(window, capabilities)?;
 
-    Ok(Swapchain {
-      swapchain, images, image_views,
-      format: format.format,
-      extent
-    })
+  let mut image_count = capabilities.min_image_count + 1;
+  if capabilities.max_image_count != 0 {
+    image_count
+        = image_count.clamp(0, capabilities.max_image_count);
   }
 
-  #[allow(unsafe_code)]
-  fn init_render_pass(device: &Device, format: &vk::Format)
-      -> Result<vk::RenderPass>
+  let mut unique_queue_family_indices = BTreeSet::new();
+  unique_queue_family_indices.insert(indices.graphics);
+  unique_queue_family_indices.insert(indices.presentation);
+
+  //   If there's only one queue, we use exclusive sharing mode, which
+  // will allow things to work without locks. Otherwise we use concurrent
+  // mode.
+  let (ordered_indices, sharing_mode)
+          = if unique_queue_family_indices.len() < 2
   {
-    let color_attachment
-            = vk::AttachmentDescription::builder()
-                  .format(*format)
-                  .samples(vk::SampleCountFlags::_1)
-                  .load_op(vk::AttachmentLoadOp::CLEAR)
-                  .store_op(vk::AttachmentStoreOp::STORE)
-                  .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
-                  .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
-                  .initial_layout(vk::ImageLayout::UNDEFINED)
-                  .final_layout(vk::ImageLayout::PRESENT_SRC_KHR);
-
-    let color_attachment_reference
-            = vk::AttachmentReference::builder()
-                  .attachment(0)
-                  .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
-
-    let subpass_attachments = [color_attachment_reference];
-    let subpass = vk::SubpassDescription::builder()
-                      .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
-                      .color_attachments(&subpass_attachments);
-
-    let dependency
-          = vk::SubpassDependency::builder()
-                .src_subpass(vk::SUBPASS_EXTERNAL)
-                .src_stage_mask(
-                     vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
-                .src_access_mask(vk::AccessFlags::empty())
-                .dst_subpass(0)
-                .dst_stage_mask(
-                     vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
-                .dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE);
-
-    let render_attachments = [color_attachment];
-    let subpasses = [subpass];
-    let dependencies = [dependency];
-    let render_pass_info = vk::RenderPassCreateInfo::builder()
-                               .attachments(&render_attachments)
-                               .subpasses(&subpasses)
-                               .dependencies(&dependencies);
-
-    let render_pass = unsafe {
-      device.create_render_pass(&render_pass_info, None)
+    (vec![indices.graphics], vk::SharingMode::EXCLUSIVE)
+  } else {
+    (vec![indices.graphics, indices.presentation],
+     vk::SharingMode::CONCURRENT)
+  };
+
+  let swapchain_info = vk::SwapchainCreateInfoKHR::builder()
+          .surface(*surface)
+          .min_image_count(image_count)
+          .image_format(format.format)
+          .image_color_space(format.color_space)
+          .image_extent(extent)
+          .image_array_layers(1)
+          .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
+          .image_sharing_mode(sharing_mode)
+          .queue_family_indices(&ordered_indices)
+          .pre_transform(capabilities.current_transform)
+          .composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
+          .present_mode(presentation_mode)
+          .clipped(true)
+          .old_swapchain(vk::SwapchainKHR::null());
+
+  let swapchain = unsafe {
+    device.create_swapchain_khr(&swapchain_info, None)
+  }?;
+
+  let images = unsafe {
+    device.get_swapchain_images_khr(swapchain)
+  }?;
+
+  let mut image_views = Vec::new();
+  for image in &images {
+    let components = vk::ComponentMapping::builder()
+                         .r(vk::ComponentSwizzle::IDENTITY)
+                         .g(vk::ComponentSwizzle::IDENTITY)
+                         .b(vk::ComponentSwizzle::IDENTITY)
+                         .a(vk::ComponentSwizzle::IDENTITY);
+
+    let subresource_range = vk::ImageSubresourceRange::builder()
+                                .aspect_mask(vk::ImageAspectFlags::COLOR)
+                                .base_mip_level(0)
+                                .level_count(1)
+                                .base_array_layer(0)
+                                .layer_count(1);
+
+    let view_info = vk::ImageViewCreateInfo::builder()
+                        .image(*image)
+                        .view_type(vk::ImageViewType::_2D)
+                        .format(format.format)
+                        .components(components)
+                        .subresource_range(subresource_range);
+
+    let view = unsafe {
+      device.create_image_view(&view_info, None)
     }?;
 
-    Ok(render_pass)
+    image_views.push(view);
   }
 
-  #[allow(unsafe_code)]
-  fn init_pipeline(device: &Device, extent: &vk::Extent2D,
-                   render_pass: &vk::RenderPass)
-      -> Result<(vk::PipelineLayout, vk::Pipeline)>
-  {
-    let vertex_binary = include_bytes!(
-            concat!(env!("OUT_DIR"), "/shader.vert.spv"));
-    let fragment_binary = include_bytes!(
-            concat!(env!("OUT_DIR"), "/shader.frag.spv"));
-
-    let vertex_module = PermanentGraphicsState::load_spirv_shader_module(
-            device, vertex_binary)?;
-    let fragment_module = PermanentGraphicsState::load_spirv_shader_module(
-            device, fragment_binary)?;
-
-    let vertex_stage_info = vk::PipelineShaderStageCreateInfo::builder()
-                                .stage(vk::ShaderStageFlags::VERTEX)
-                                .module(vertex_module)
-                                .name(b"main\0");
+  Ok(Swapchain {
+    swapchain, images, image_views,
+    format: format.format,
+    extent
+  })
+}
 
-    let fragment_stage_info = vk::PipelineShaderStageCreateInfo::builder()
-                                  .stage(vk::ShaderStageFlags::FRAGMENT)
-                                  .module(fragment_module)
-                                  .name(b"main\0");
-
-    let vertex_input_state_info
-            = vk::PipelineVertexInputStateCreateInfo::builder();
-
-    let input_assembly_state_info
-            = vk::PipelineInputAssemblyStateCreateInfo::builder()
-                  .topology(vk::PrimitiveTopology::TRIANGLE_LIST)
-                  .primitive_restart_enable(false);
-
-    let viewport = vk::Viewport::builder()
-                       .x(0.0)
-                       .y(0.0)
-                       .width(extent.width as f32)
-                       .height(extent.height as f32)
-                       .min_depth(0.0)
-                       .max_depth(1.0);
-    let viewports = [viewport];
-
-    let scissor = vk::Rect2D::builder()
-                       .offset(vk::Offset2D { x: 0, y: 0 })
-                       .extent(*extent);
-    let scissor_list = [scissor];
-
-    let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
-                       .viewports(&viewports)
-                       .scissors(&scissor_list);
-
-    let rasterizer_state_info
-            = vk::PipelineRasterizationStateCreateInfo::builder()
-                  .depth_clamp_enable(false)
-                  .rasterizer_discard_enable(false)
-                  .polygon_mode(vk::PolygonMode::FILL)
-                  .line_width(1.0)
-                  .cull_mode(vk::CullModeFlags::BACK)
-                  .front_face(vk::FrontFace::CLOCKWISE)
-                  .depth_bias_enable(false);
-
-    let multisample_state_info
-            = vk::PipelineMultisampleStateCreateInfo::builder()
-                  .sample_shading_enable(false)
-                  .rasterization_samples(vk::SampleCountFlags::_1);
-
-    let blend_attachment_info
-            = vk::PipelineColorBlendAttachmentState::builder()
-                  .color_write_mask(vk::ColorComponentFlags::all())
-                  .blend_enable(false)
-                  .src_color_blend_factor(vk::BlendFactor::ONE)
-                  .dst_color_blend_factor(vk::BlendFactor::ZERO)
-                  .color_blend_op(vk::BlendOp::ADD)
-                  .src_alpha_blend_factor(vk::BlendFactor::ONE)
-                  .dst_alpha_blend_factor(vk::BlendFactor::ZERO)
-                  .alpha_blend_op(vk::BlendOp::ADD);
-    let blend_attachments = [blend_attachment_info];
-
-    let blend_info = vk::PipelineColorBlendStateCreateInfo::builder()
-                         .logic_op_enable(false)
-                         .logic_op(vk::LogicOp::COPY)
-                         .attachments(&blend_attachments)
-                         .blend_constants([0.0, 0.0, 0.0, 0.0]);
-
-    let pipeline_layout_info = vk::PipelineLayoutCreateInfo::builder();
-
-    let pipeline_layout = unsafe {
-      device.create_pipeline_layout(&pipeline_layout_info, None)
-    }?;
 
-    let stages = [vertex_stage_info, fragment_stage_info];
-    let pipeline_info
-            = vk::GraphicsPipelineCreateInfo::builder()
-                  .stages(&stages)
-                  .vertex_input_state(&vertex_input_state_info)
-                  .input_assembly_state(&input_assembly_state_info)
-                  .viewport_state(&viewport_state_info)
-                  .rasterization_state(&rasterizer_state_info)
-                  .multisample_state(&multisample_state_info)
-                  .color_blend_state(&blend_info)
-                  .layout(pipeline_layout)
-                  .render_pass(*render_pass)
-                  .subpass(0);
-
-    let pipeline = unsafe {
-      device.create_graphics_pipelines(vk::PipelineCache::null(),
-                                       &[pipeline_info], None)
-    }?.0[0];
+#[allow(unsafe_code)]
+fn init_render_pass(device: &Device, format: &vk::Format)
+    -> Result<vk::RenderPass>
+{
+  let color_attachment
+          = vk::AttachmentDescription::builder()
+                .format(*format)
+                .samples(vk::SampleCountFlags::_1)
+                .load_op(vk::AttachmentLoadOp::CLEAR)
+                .store_op(vk::AttachmentStoreOp::STORE)
+                .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE)
+                .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE)
+                .initial_layout(vk::ImageLayout::UNDEFINED)
+                .final_layout(vk::ImageLayout::PRESENT_SRC_KHR);
+
+  let color_attachment_reference
+          = vk::AttachmentReference::builder()
+                .attachment(0)
+                .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL);
+
+  let subpass_attachments = [color_attachment_reference];
+  let subpass = vk::SubpassDescription::builder()
+                    .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
+                    .color_attachments(&subpass_attachments);
+
+  let dependency
+        = vk::SubpassDependency::builder()
+              .src_subpass(vk::SUBPASS_EXTERNAL)
+              .src_stage_mask(
+                   vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
+              .src_access_mask(vk::AccessFlags::empty())
+              .dst_subpass(0)
+              .dst_stage_mask(
+                   vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT)
+              .dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE);
+
+  let render_attachments = [color_attachment];
+  let subpasses = [subpass];
+  let dependencies = [dependency];
+  let render_pass_info = vk::RenderPassCreateInfo::builder()
+                             .attachments(&render_attachments)
+                             .subpasses(&subpasses)
+                             .dependencies(&dependencies);
+
+  let render_pass = unsafe {
+    device.create_render_pass(&render_pass_info, None)
+  }?;
+
+  Ok(render_pass)
+}
 
-    unsafe {
-      device.destroy_shader_module(vertex_module, None);
-      device.destroy_shader_module(fragment_module, None);
-    };
 
-    Ok((pipeline_layout, pipeline))
-  }
+#[allow(unsafe_code)]
+fn init_pipeline(device: &Device, extent: &vk::Extent2D,
+                 render_pass: &vk::RenderPass)
+    -> Result<(vk::PipelineLayout, vk::Pipeline)>
+{
+  let vertex_binary = include_bytes!(
+          concat!(env!("OUT_DIR"), "/shader.vert.spv"));
+  let fragment_binary = include_bytes!(
+          concat!(env!("OUT_DIR"), "/shader.frag.spv"));
+
+  let vertex_module = PermanentGraphicsState::load_spirv_shader_module(
+          device, vertex_binary)?;
+  let fragment_module = PermanentGraphicsState::load_spirv_shader_module(
+          device, fragment_binary)?;
+
+  let vertex_stage_info = vk::PipelineShaderStageCreateInfo::builder()
+                              .stage(vk::ShaderStageFlags::VERTEX)
+                              .module(vertex_module)
+                              .name(b"main\0");
+
+  let fragment_stage_info = vk::PipelineShaderStageCreateInfo::builder()
+                                .stage(vk::ShaderStageFlags::FRAGMENT)
+                                .module(fragment_module)
+                                .name(b"main\0");
 
-  #[allow(unsafe_code)]
-  fn init_framebuffers(device: &Device, extent: &vk::Extent2D,
-                       swapchain_image_views: &Vec<vk::ImageView>,
-                       render_pass: &vk::RenderPass)
-      -> Result<Vec<vk::Framebuffer>>
-  {
-    let mut framebuffers = Vec::new();
+  let vertex_input_state_info
+          = vk::PipelineVertexInputStateCreateInfo::builder();
+
+  let input_assembly_state_info
+          = vk::PipelineInputAssemblyStateCreateInfo::builder()
+                .topology(vk::PrimitiveTopology::TRIANGLE_LIST)
+                .primitive_restart_enable(false);
+
+  let viewport = vk::Viewport::builder()
+                     .x(0.0)
+                     .y(0.0)
+                     .width(extent.width as f32)
+                     .height(extent.height as f32)
+                     .min_depth(0.0)
+                     .max_depth(1.0);
+  let viewports = [viewport];
+
+  let scissor = vk::Rect2D::builder()
+                     .offset(vk::Offset2D { x: 0, y: 0 })
+                     .extent(*extent);
+  let scissor_list = [scissor];
+
+  let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
+                     .viewports(&viewports)
+                     .scissors(&scissor_list);
+
+  let rasterizer_state_info
+          = vk::PipelineRasterizationStateCreateInfo::builder()
+                .depth_clamp_enable(false)
+                .rasterizer_discard_enable(false)
+                .polygon_mode(vk::PolygonMode::FILL)
+                .line_width(1.0)
+                .cull_mode(vk::CullModeFlags::BACK)
+                .front_face(vk::FrontFace::CLOCKWISE)
+                .depth_bias_enable(false);
+
+  let multisample_state_info
+          = vk::PipelineMultisampleStateCreateInfo::builder()
+                .sample_shading_enable(false)
+                .rasterization_samples(vk::SampleCountFlags::_1);
+
+  let blend_attachment_info
+          = vk::PipelineColorBlendAttachmentState::builder()
+                .color_write_mask(vk::ColorComponentFlags::all())
+                .blend_enable(false)
+                .src_color_blend_factor(vk::BlendFactor::ONE)
+                .dst_color_blend_factor(vk::BlendFactor::ZERO)
+                .color_blend_op(vk::BlendOp::ADD)
+                .src_alpha_blend_factor(vk::BlendFactor::ONE)
+                .dst_alpha_blend_factor(vk::BlendFactor::ZERO)
+                .alpha_blend_op(vk::BlendOp::ADD);
+  let blend_attachments = [blend_attachment_info];
+
+  let blend_info = vk::PipelineColorBlendStateCreateInfo::builder()
+                       .logic_op_enable(false)
+                       .logic_op(vk::LogicOp::COPY)
+                       .attachments(&blend_attachments)
+                       .blend_constants([0.0, 0.0, 0.0, 0.0]);
+
+  let pipeline_layout_info = vk::PipelineLayoutCreateInfo::builder();
+
+  let pipeline_layout = unsafe {
+    device.create_pipeline_layout(&pipeline_layout_info, None)
+  }?;
+
+  let stages = [vertex_stage_info, fragment_stage_info];
+  let pipeline_info
+          = vk::GraphicsPipelineCreateInfo::builder()
+                .stages(&stages)
+                .vertex_input_state(&vertex_input_state_info)
+                .input_assembly_state(&input_assembly_state_info)
+                .viewport_state(&viewport_state_info)
+                .rasterization_state(&rasterizer_state_info)
+                .multisample_state(&multisample_state_info)
+                .color_blend_state(&blend_info)
+                .layout(pipeline_layout)
+                .render_pass(*render_pass)
+                .subpass(0);
+
+  let pipeline = unsafe {
+    device.create_graphics_pipelines(vk::PipelineCache::null(),
+                                     &[pipeline_info], None)
+  }?.0[0];
+
+  unsafe {
+    device.destroy_shader_module(vertex_module, None);
+    device.destroy_shader_module(fragment_module, None);
+  };
+
+  Ok((pipeline_layout, pipeline))
+}
 
-    for image_view in swapchain_image_views {
-      let attachments = [*image_view];
 
-      let framebuffer_info = vk::FramebufferCreateInfo::builder()
-                                 .render_pass(*render_pass)
-                                 .attachments(&attachments)
-                                 .width(extent.width)
-                                 .height(extent.height)
-                                 .layers(1);
+#[allow(unsafe_code)]
+fn init_framebuffers(device: &Device, extent: &vk::Extent2D,
+                     swapchain_image_views: &Vec<vk::ImageView>,
+                     render_pass: &vk::RenderPass)
+    -> Result<Vec<vk::Framebuffer>>
+{
+  let mut framebuffers = Vec::new();
 
-      let framebuffer = unsafe {
-        device.create_framebuffer(&framebuffer_info, None)
-      }?;
+  for image_view in swapchain_image_views {
+    let attachments = [*image_view];
 
-      framebuffers.push(framebuffer);
-    }
+    let framebuffer_info = vk::FramebufferCreateInfo::builder()
+                               .render_pass(*render_pass)
+                               .attachments(&attachments)
+                               .width(extent.width)
+                               .height(extent.height)
+                               .layers(1);
 
-    Ok(framebuffers)
+    let framebuffer = unsafe {
+      device.create_framebuffer(&framebuffer_info, None)
+    }?;
+
+    framebuffers.push(framebuffer);
   }
 
-  #[allow(unsafe_code)]
-  fn init_commands(device: &Device,
-                   extent: &vk::Extent2D,
-                   framebuffers: &Vec<vk::Framebuffer>,
-                   render_pass: &vk::RenderPass,
-                   pipeline: &vk::Pipeline,
-                   indices: &QueueFamilyIndices)
-      -> Result<(vk::CommandPool, Vec<vk::CommandBuffer>)>
-  {
-    // We call this one last time. It's kind of a problem.
+  Ok(framebuffers)
+}
 
-    let command_pool_info = vk::CommandPoolCreateInfo::builder()
-                                .flags(vk::CommandPoolCreateFlags::empty())
-                                .queue_family_index(indices.graphics);
 
-    let command_pool = unsafe {
-      device.create_command_pool(&command_pool_info, None)
-    }?;
+#[allow(unsafe_code)]
+fn init_commands(device: &Device,
+                 extent: &vk::Extent2D,
+                 framebuffers: &Vec<vk::Framebuffer>,
+                 render_pass: &vk::RenderPass,
+                 pipeline: &vk::Pipeline,
+                 indices: &QueueFamilyIndices)
+    -> Result<(vk::CommandPool, Vec<vk::CommandBuffer>)>
+{
+  // We call this one last time. It's kind of a problem.
+
+  let command_pool_info = vk::CommandPoolCreateInfo::builder()
+                              .flags(vk::CommandPoolCreateFlags::empty())
+                              .queue_family_index(indices.graphics);
+
+  let command_pool = unsafe {
+    device.create_command_pool(&command_pool_info, None)
+  }?;
+
+  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)
+  }?;
+
+  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);
 
-    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)
+    unsafe {
+      device.begin_command_buffer(command_buffer,
+                                  &command_buffer_begin_info)
     }?;
 
-    for (index, framebuffer) in framebuffers.iter().enumerate() {
-      let command_buffer = command_buffers[index];
+    let render_area = vk::Rect2D::builder()
+                          .offset(vk::Offset2D::default())
+                          .extent(*extent);
 
-      let inheritance_info = vk::CommandBufferInheritanceInfo::builder();
-
-      let command_buffer_begin_info
-              = vk::CommandBufferBeginInfo::builder()
-                    .flags(vk::CommandBufferUsageFlags::empty())
-                    .inheritance_info(&inheritance_info);
+    let clear_value = vk::ClearValue {
+      color: vk::ClearColorValue {
+        float32: [0.0, 0.0, 0.0, 1.0]
+      }
+    };
+    let clear_values = [clear_value];
 
-      unsafe {
-        device.begin_command_buffer(command_buffer,
-                                    &command_buffer_begin_info)
-      }?;
+    let begin_pass_info = vk::RenderPassBeginInfo::builder()
+                              .render_pass(*render_pass)
+                              .framebuffer(*framebuffer)
+                              .render_area(render_area)
+                              .clear_values(&clear_values);
 
-      let render_area = vk::Rect2D::builder()
-                            .offset(vk::Offset2D::default())
-                            .extent(*extent);
+    unsafe {
+      device.cmd_begin_render_pass(command_buffer, &begin_pass_info,
+                                   vk::SubpassContents::INLINE)
+    };
 
-      let clear_value = vk::ClearValue {
-        color: vk::ClearColorValue {
-          float32: [0.0, 0.0, 0.0, 1.0]
-        }
-      };
-      let clear_values = [clear_value];
+    unsafe {
+      device.cmd_bind_pipeline(command_buffer,
+                               vk::PipelineBindPoint::GRAPHICS,
+                               *pipeline)
+    };
 
-      let begin_pass_info = vk::RenderPassBeginInfo::builder()
-                                .render_pass(*render_pass)
-                                .framebuffer(*framebuffer)
-                                .render_area(render_area)
-                                .clear_values(&clear_values);
+    unsafe { device.cmd_draw(command_buffer, 3, 1, 0, 0) };
 
-      unsafe {
-        device.cmd_begin_render_pass(command_buffer, &begin_pass_info,
-                                     vk::SubpassContents::INLINE)
-      };
+    unsafe { device.cmd_end_render_pass(command_buffer) };
 
-      unsafe {
-        device.cmd_bind_pipeline(command_buffer,
-                                 vk::PipelineBindPoint::GRAPHICS,
-                                 *pipeline)
-      };
+    unsafe { device.end_command_buffer(command_buffer) }?;
+  }
 
-      unsafe { device.cmd_draw(command_buffer, 3, 1, 0, 0) };
+  Ok((command_pool, command_buffers))
+}
 
-      unsafe { device.cmd_end_render_pass(command_buffer) };
 
-      unsafe { device.end_command_buffer(command_buffer) }?;
-    }
+#[allow(unsafe_code)]
+fn init_concurrency(device: &Device,
+                    swapchain_images: &Vec<vk::Image>)
+    -> Result<Concurrency>
+{
+  let semaphore_info = vk::SemaphoreCreateInfo::builder();
+  let fence_info = vk::FenceCreateInfo::builder()
+                       .flags(vk::FenceCreateFlags::SIGNALED);
+
+  let mut image_available_semaphores = Vec::new();
+  let mut rendering_finished_semaphores = Vec::new();
+  let mut frame_fences = Vec::new();
+  for _ in 0 .. N_SIMULTANEOUS_FRAMES {
+    image_available_semaphores.push(unsafe {
+      device.create_semaphore(&semaphore_info, None)
+    }?);
+
+    rendering_finished_semaphores.push(unsafe {
+      device.create_semaphore(&semaphore_info, None)
+    }?);
+
+    frame_fences.push(unsafe {
+      device.create_fence(&fence_info, None)
+    }?);
+  }
 
-    Ok((command_pool, command_buffers))
+  let mut image_fences = Vec::new();
+  for _ in 0 .. swapchain_images.len() {
+    image_fences.push(vk::Fence::null());
   }
 
-  #[allow(unsafe_code)]
-  fn init_concurrency(device: &Device,
-                      swapchain_images: &Vec<vk::Image>)
-      -> Result<Concurrency>
-  {
-    let semaphore_info = vk::SemaphoreCreateInfo::builder();
-    let fence_info = vk::FenceCreateInfo::builder()
-                         .flags(vk::FenceCreateFlags::SIGNALED);
-
-    let mut image_available_semaphores = Vec::new();
-    let mut rendering_finished_semaphores = Vec::new();
-    let mut frame_fences = Vec::new();
-    for _ in 0 .. N_SIMULTANEOUS_FRAMES {
-      image_available_semaphores.push(unsafe {
-        device.create_semaphore(&semaphore_info, None)
-      }?);
-
-      rendering_finished_semaphores.push(unsafe {
-        device.create_semaphore(&semaphore_info, None)
-      }?);
-
-      frame_fences.push(unsafe {
-        device.create_fence(&fence_info, None)
-      }?);
-    }
+  Ok(Concurrency {
+    image_available_semaphores,
+    rendering_finished_semaphores,
+    frame_fences,
+    image_fences: image_fences,
+  })
+}
 
-    let mut image_fences = Vec::new();
-    for _ in 0 .. swapchain_images.len() {
-      image_fences.push(vk::Fence::null());
-    }
 
-    Ok(Concurrency {
-      image_available_semaphores,
-      rendering_finished_semaphores,
-      frame_fences,
-      image_fences: image_fences,
-    })
+fn pick_surface_format(available_formats: &Vec<vk::SurfaceFormatKHR>)
+    -> Result<vk::SurfaceFormatKHR>
+{
+  for format in available_formats {
+    if format.format == vk::Format::B8G8R8A8_SRGB
+       && format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
+    {
+      return Ok(format.clone());
+    }
   }
 
-  fn pick_surface_format(available_formats: &Vec<vk::SurfaceFormatKHR>)
-      -> Result<vk::SurfaceFormatKHR>
-  {
-    for format in available_formats {
-      if format.format == vk::Format::B8G8R8A8_SRGB
-         && format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
-      {
-        return Ok(format.clone());
-      }
-    }
+  return Ok(available_formats[0].clone());
+}
 
-    return Ok(available_formats[0].clone());
-  }
 
-  fn pick_presentation_mode(_available_modes: &Vec<vk::PresentModeKHR>)
-      -> Result<vk::PresentModeKHR>
-  {
-    // It's guaranteed to have this one.
-    return Ok(vk::PresentModeKHR::FIFO);
-  }
+fn pick_presentation_mode(_available_modes: &Vec<vk::PresentModeKHR>)
+    -> Result<vk::PresentModeKHR>
+{
+  // It's guaranteed to have this one.
+  return Ok(vk::PresentModeKHR::FIFO);
+}
 
-  fn pick_image_extent(window: &Window,
-                       capabilities: vk::SurfaceCapabilitiesKHR)
-      -> Result<vk::Extent2D>
+
+fn pick_image_extent(window: &Window,
+                     capabilities: vk::SurfaceCapabilitiesKHR)
+    -> Result<vk::Extent2D>
+{
+  if capabilities.current_extent.width != u32::MAX
+     && capabilities.current_extent.height != u32::MAX
   {
-    if capabilities.current_extent.width != u32::MAX
-       && capabilities.current_extent.height != u32::MAX
-    {
-      Ok(capabilities.current_extent)
-    } else {
-      let window_size = window.inner_size();
-
-      let width = window_size.width
-                             .clamp(capabilities.min_image_extent.width,
-                                    capabilities.max_image_extent.width);
-      let height = window_size.height
-                              .clamp(capabilities.min_image_extent.height,
-                                     capabilities.max_image_extent.height);
-
-      Ok(vk::Extent2D::builder().width(width).height(height).build())
-    }
+    Ok(capabilities.current_extent)
+  } else {
+    let window_size = window.inner_size();
+
+    let width = window_size.width
+                           .clamp(capabilities.min_image_extent.width,
+                                  capabilities.max_image_extent.width);
+    let height = window_size.height
+                            .clamp(capabilities.min_image_extent.height,
+                                   capabilities.max_image_extent.height);
+
+    Ok(vk::Extent2D::builder().width(width).height(height).build())
   }
 }
+