summary refs log tree commit diff
path: root/src/graphics/window_dressing.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics/window_dressing.rs')
-rw-r--r--src/graphics/window_dressing.rs458
1 files changed, 2 insertions, 456 deletions
diff --git a/src/graphics/window_dressing.rs b/src/graphics/window_dressing.rs
index 09410bc..9afb03e 100644
--- a/src/graphics/window_dressing.rs
+++ b/src/graphics/window_dressing.rs
@@ -5,17 +5,13 @@ use crate::graphics::permanent::{
   EnableAnisotropy
 };
 use crate::graphics::util::{
-  allocate_buffer, stage_in_buffer,
-  pick_memory_type,
-  begin_transient_commands, end_transient_commands
+  allocate_buffer, allocate_image, init_image_view
 };
 use crate::shader_data::UniformBlock;
 
 use std::collections::BTreeSet;
-use std::io::Cursor;
 use std::mem::size_of;
 
-use png::Decoder;
 use vulkanalia::{ Device, Instance };
 use vulkanalia::vk::{ self, Handle, HasBuilder, InstanceV1_0, DeviceV1_0,
                       KhrSwapchainExtensionDeviceCommands };
@@ -46,12 +42,6 @@ pub struct WindowDressing {
   pub depth_image_view: vk::ImageView,
   pub depth_format: vk::Format,
 
-  pub primary_command_pool: vk::CommandPool,
-  pub transient_command_pool: vk::CommandPool,
-
-  texture_image: vk::Image,
-  texture_image_memory: vk::DeviceMemory,
-  pub texture_image_view: vk::ImageView,
   pub sampler: vk::Sampler,
 
   pub uniform_buffers: Vec<vk::Buffer>,
@@ -101,14 +91,13 @@ pub struct Concurrency {
 impl WindowDressing {
   pub fn new(permanent: &PermanentGraphicsState,
              for_reinit: &GraphicsStateForReinit,
-             enable_anisotropy: EnableAnisotropy)
+             enable_anisotropy: EnableAnisotropy, mip_count: u32)
       -> Result<Self>
   {
     let window = &permanent.window;
     let instance = &permanent.instance;
     let surface = &permanent.surface;
     let device = &permanent.device;
-    let graphics_queue = &permanent.graphics_queue;
     let sample_count = for_reinit.sample_count;
     let indices = &for_reinit.indices;
 
@@ -122,13 +111,6 @@ impl WindowDressing {
     let (depth_image, depth_image_memory, depth_image_view, depth_format)
             = init_depth(instance, device, &swapchain.extent, sample_count)?;
 
-    let (primary_command_pool, transient_command_pool)
-            = init_command_pools(device, indices)?;
-
-    let (texture_image, texture_image_memory, texture_image_view, mip_count)
-            = init_texture(instance, device, graphics_queue,
-                           &transient_command_pool)?;
-
     let sampler = init_sampler(&device, &enable_anisotropy, mip_count)?;
 
     let (uniform_buffers, uniform_buffer_memory)
@@ -148,15 +130,10 @@ impl WindowDressing {
       depth_image_memory,
       depth_image_view,
       depth_format,
-      texture_image,
-      texture_image_memory,
-      texture_image_view,
       sampler,
       uniform_buffers,
       uniform_buffer_memory,
       descriptor_pool,
-      primary_command_pool,
-      transient_command_pool,
       concurrency,
     })
   }
@@ -220,9 +197,6 @@ impl WindowDressing {
   pub fn destroy(mut self, device: &Device) {
     self.destroy_replaceable(device);
 
-    unsafe { device.destroy_image(self.texture_image, None) };
-    unsafe { device.free_memory(self.texture_image_memory, None) };
-    unsafe { device.destroy_image_view(self.texture_image_view, None) };
     unsafe { device.destroy_sampler(self.sampler, None) };
 
     for semaphore in self.concurrency.image_available_semaphores {
@@ -236,11 +210,6 @@ impl WindowDressing {
     for fence in self.concurrency.frame_fences {
       unsafe { device.destroy_fence(fence, None) };
     }
-
-    //   Notice that destroy_replaceable() freed the buffers in the pools, but
-    // did not destroy the pools.
-    unsafe { device.destroy_command_pool(self.primary_command_pool, None) };
-    unsafe { device.destroy_command_pool(self.transient_command_pool, None) };
   }
 
 
@@ -400,74 +369,6 @@ fn init_depth(instance: &Instance, device: &Device, extent: &vk::Extent2D,
 }
 
 
-#[allow(unsafe_code)]
-fn init_texture(instance: &Instance, device: &Device, queue: &vk::Queue,
-                command_pool: &vk::CommandPool)
-    -> Result<(vk::Image, vk::DeviceMemory, vk::ImageView, u32)>
-{
-  let physical_device = device.physical_device();
-
-  let png = include_bytes!("../../textures/forest_leaves_04_diff.png");
-
-  let decoder = Decoder::new(Cursor::new(png));
-  let mut reader = decoder.read_info()?;
-
-  let (width, height) = reader.info().size();
-
-  let format_properties = unsafe {
-    instance.get_physical_device_format_properties(physical_device,
-                                                   vk::Format::R8G8B8A8_SRGB)
-  };
-  let has_linear_filter = format_properties
-          .optimal_tiling_features
-          .contains(vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_LINEAR);
-  let mip_count = if has_linear_filter {
-    //   This will generate mips all the way down to 1x1. It is not clear
-    // whether there's a benefit to that.
-    (width.max(height)).ilog2() + 1
-  } else {
-    1
-  };
-
-  let mut pixels = vec![0; reader.info().raw_bytes()];
-  reader.next_frame(&mut pixels)?;
-
-  let (staging_buffer, staging_memory, _byte_size)
-          = stage_in_buffer(instance, device, &pixels)?;
-
-  let (image, image_memory)
-          = allocate_image(instance, device,
-                           width, height, mip_count, vk::SampleCountFlags::_1,
-                           vk::Format::R8G8B8A8_SRGB,
-                           vk::ImageTiling::OPTIMAL,
-                           vk::ImageUsageFlags::SAMPLED
-                               | vk::ImageUsageFlags::TRANSFER_SRC
-                               | vk::ImageUsageFlags::TRANSFER_DST,
-                           vk::MemoryPropertyFlags::DEVICE_LOCAL)?;
-
-  change_image_layout(device, queue, command_pool, &image, mip_count,
-                      vk::ImageLayout::UNDEFINED,
-                      vk::ImageLayout::TRANSFER_DST_OPTIMAL)?;
-
-  copy_buffer_to_image(device, queue, command_pool, &staging_buffer, &image,
-                       width, height)?;
-
-  // This will also change the layout to SHADER_READ_ONLY_OPTIMAL.
-
-  fill_mip_levels(device, queue, command_pool, &image,
-                  width, height, mip_count)?;
-
-  let view = init_image_view(device, &image, mip_count,
-                             vk::Format::R8G8B8A8_SRGB,
-                             vk::ImageAspectFlags::COLOR)?;
-
-  unsafe { device.destroy_buffer(staging_buffer, None) };
-  unsafe { device.free_memory(staging_memory, None) };
-
-  Ok((image, image_memory, view, mip_count))
-}
-
-
 fn init_uniform_buffers(instance: &Instance, device: &Device, count: usize)
     -> Result<(Vec<vk::Buffer>, Vec<vk::DeviceMemory>)>
 {
@@ -545,28 +446,6 @@ fn init_descriptor_pool(device: &Device, count: usize)
 
 
 #[allow(unsafe_code)]
-fn init_command_pools(device: &Device, indices: &QueueFamilyIndices)
-    -> Result<(vk::CommandPool, vk::CommandPool)>
-{
-  let command_pool_info = vk::CommandPoolCreateInfo::builder()
-          .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)
-  }?;
-
-  command_pool_info.flags(vk::CommandPoolCreateFlags::TRANSIENT);
-  let transient = unsafe {
-    device.create_command_pool(&command_pool_info, None)
-  }?;
-
-  Ok((primary, transient))
-}
-
-
-#[allow(unsafe_code)]
 fn init_concurrency(device: &Device,
                     swapchain_images: &Vec<vk::Image>)
     -> Result<Concurrency>
@@ -606,41 +485,6 @@ fn init_concurrency(device: &Device,
 }
 
 
-#[allow(unsafe_code)]
-fn init_image_view(device: &Device, image: &vk::Image, mip_count: u32,
-                   format: vk::Format, aspects: vk::ImageAspectFlags)
-    -> Result<vk::ImageView>
-{
-  //   Component mapping is only for color components (not, for example, depth
-  // or stencil components), so we always just want it like this.
-  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(aspects)
-          .base_mip_level(0)
-          .level_count(mip_count)
-          .base_array_layer(0)
-          .layer_count(1);
-
-  let view_info = vk::ImageViewCreateInfo::builder()
-          .image(*image)
-          .view_type(vk::ImageViewType::_2D)
-          .format(format)
-          .components(components)
-          .subresource_range(subresource_range);
-
-  let view = unsafe {
-    device.create_image_view(&view_info, None)
-  }?;
-
-  Ok(view)
-}
-
-
 fn pick_surface_format(available_formats: &Vec<vk::SurfaceFormatKHR>)
     -> Result<vk::SurfaceFormatKHR>
 {
@@ -713,301 +557,3 @@ fn pick_image_extent(window: &Window,
   }
 }
 
-
-#[allow(unsafe_code)]
-fn allocate_image(instance: &Instance, device: &Device, width: u32,
-                  height: u32, mip_count: u32,
-                  sample_count: vk::SampleCountFlags, format: vk::Format,
-                  tiling: vk::ImageTiling, usage: vk::ImageUsageFlags,
-                  memory_flags: vk::MemoryPropertyFlags)
-    -> Result<(vk::Image, vk::DeviceMemory)>
-{
-  let physical_device = device.physical_device();
-
-  let image_info = vk::ImageCreateInfo::builder()
-          .image_type(vk::ImageType::_2D)
-          .extent(vk::Extent3D { width, height, depth: 1 })
-          .mip_levels(mip_count)
-          .samples(sample_count)
-          .array_layers(1)
-          .format(format)
-          .tiling(tiling)
-          .initial_layout(vk::ImageLayout::UNDEFINED)
-          .usage(usage)
-          .sharing_mode(vk::SharingMode::EXCLUSIVE)
-          .flags(vk::ImageCreateFlags::empty());
-  let image = unsafe { device.create_image(&image_info, None) }?;
-
-  let requirements = unsafe { device.get_image_memory_requirements(image) };
-
-  let type_index = pick_memory_type(instance, &physical_device,
-                                    &memory_flags, &requirements)?;
-
-  let image_memory_info = vk::MemoryAllocateInfo::builder()
-          .allocation_size(requirements.size)
-          .memory_type_index(type_index);
-  let image_memory = unsafe {
-    device.allocate_memory(&image_memory_info, None)
-  }?;
-
-  unsafe { device.bind_image_memory(image, image_memory, 0) }?;
-
-  Ok((image, image_memory))
-}
-
-
-#[allow(unsafe_code)]
-fn copy_buffer_to_image(device: &Device, queue: &vk::Queue,
-                        command_pool: &vk::CommandPool, source: &vk::Buffer,
-                        destination: &vk::Image, width: u32, height: u32)
-    -> Result<()>
-{
-  let command_buffer = begin_transient_commands(device, command_pool)?;
-
-  let subresource_layers = vk::ImageSubresourceLayers::builder()
-          .aspect_mask(vk::ImageAspectFlags::COLOR)
-          .mip_level(0)
-          .base_array_layer(0)
-          .layer_count(1);
-
-  let copy_info = vk::BufferImageCopy::builder()
-          .buffer_offset(0)
-          .buffer_row_length(0)
-          .buffer_image_height(0)
-          .image_subresource(subresource_layers)
-          .image_offset(vk::Offset3D { x: 0, y: 0, z: 0 })
-          .image_extent(vk::Extent3D { width, height, depth: 1 });
-
-  unsafe {
-    device.cmd_copy_buffer_to_image(command_buffer, *source, *destination,
-                                    vk::ImageLayout::TRANSFER_DST_OPTIMAL,
-                                    &[copy_info])
-  };
-
-  end_transient_commands(command_buffer, device, queue, command_pool)?;
-
-  Ok(())
-}
-
-
-#[allow(unsafe_code)]
-fn change_image_layout(device: &Device, queue: &vk::Queue,
-                       command_pool: &vk::CommandPool, image: &vk::Image,
-                       mip_count: u32, old: vk::ImageLayout,
-                       new: vk::ImageLayout)
-    -> Result<()>
-{
-  let command_buffer = begin_transient_commands(device, command_pool)?;
-
-  let subresource_range = vk::ImageSubresourceRange::builder()
-          .aspect_mask(vk::ImageAspectFlags::COLOR)
-          .base_mip_level(0)
-          .level_count(mip_count)
-          .base_array_layer(0)
-          .layer_count(1);
-
-  //   Notionally this is a property that our caller is in a better position
-  // to know than we are, but in practice the nature of the transition
-  // strongly implies a particular phase of the image's lifecycle, so we just
-  // compute it here.
-  let (source_access, source_stage, destination_access, destination_stage)
-          = match (old, new)
-  {
-    (vk::ImageLayout::UNDEFINED, vk::ImageLayout::TRANSFER_DST_OPTIMAL)
-        => (vk::AccessFlags::empty(),
-            vk::PipelineStageFlags::TOP_OF_PIPE,
-            vk::AccessFlags::TRANSFER_WRITE,
-            vk::PipelineStageFlags::TRANSFER),
-    (vk::ImageLayout::TRANSFER_DST_OPTIMAL,
-     vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
-        => (vk::AccessFlags::TRANSFER_WRITE,
-            vk::PipelineStageFlags::TRANSFER,
-            vk::AccessFlags::SHADER_READ,
-            vk::PipelineStageFlags::FRAGMENT_SHADER),
-    _ => return Err(Error {
-      message:
-          format!("Don't know how to change from image layout {:?} to {:?}",
-                  old, new)
-    })
-  };
-
-  let barrier_info = vk::ImageMemoryBarrier::builder()
-        .image(*image)
-        .subresource_range(subresource_range)
-        .old_layout(old)
-        .new_layout(new)
-        .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
-        .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
-        .src_access_mask(source_access)
-        .dst_access_mask(destination_access);
-
-  unsafe {
-    device.cmd_pipeline_barrier(command_buffer,
-                                source_stage, destination_stage,
-                                vk::DependencyFlags::empty(),
-                                &[] as &[vk::MemoryBarrier],
-                                &[] as &[vk::BufferMemoryBarrier],
-                                &[barrier_info])
-  };
-
-  end_transient_commands(command_buffer, device, queue, command_pool)?;
-
-  Ok(())
-}
-
-
-//   An Image can store multiple mip levels within it, as one of several kinds
-// of subresource it has. We deal with this by
-#[allow(unsafe_code)]
-fn fill_mip_levels(device: &Device, queue: &vk::Queue,
-                   command_pool: &vk::CommandPool, image: &vk::Image,
-                   original_width: u32, original_height: u32,
-                   mip_count: u32)
-    -> Result<()>
-{
-  let command_buffer = begin_transient_commands(device, command_pool)?;
-
-  //   We'll be mutating these two builders as we loop through the mip levels,
-  // because we need to construct a lot of similar things. Remember, the
-  // builder methods don't mutate in-place, they return a new builder; to
-  // avoid confusion we always assign that result back to the same variable.
-  let mut barrier_subresource_range = vk::ImageSubresourceRange::builder()
-          .aspect_mask(vk::ImageAspectFlags::COLOR)
-          .level_count(1)
-          .base_array_layer(0)
-          .layer_count(1);
-
-  let mut blit_barrier_info = vk::ImageMemoryBarrier::builder()
-          .image(*image)
-          .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
-          .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED);
-
-  //   Now we loop through the mip levels from largest (low numbers) to
-  // smallest (high numbers). Conceptually, the only thing we're doing is a
-  // blit that copies each mip level from the one immediately before. Recall
-  // though that we don't just want to fill in the pixels, we also care about
-  // pixel format and memory sharing. There are additional operations to deal
-  // with that. These are best done together, as detailed below.
-  //
-  //   This loop has a lot of code in it, so we make the "paragraphs" a little
-  // more dense than usual to make sure the logical grouping is clear.
-  let mut source_width = original_width;
-  let mut source_height = original_height;
-  for destination_mip_level in 1 .. mip_count {
-    let source_mip_level = destination_mip_level - 1;
-    let destination_width = (source_width / 2).max(1);
-    let destination_height = (source_height / 2).max(1);
-
-    //   So. The name pipeline_barrier is a little misleading; it does indeed
-    // mean "barrier" in the concurrency sense, but it isn't just initiating
-    // a wait, it's also performing any needed mutation. We do one of them
-    // here, acting on this iteration's source level, to set it up for
-    // reading.
-    barrier_subresource_range = barrier_subresource_range
-        .base_mip_level(source_mip_level as u32);
-    blit_barrier_info = blit_barrier_info
-        .old_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
-        .new_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL)
-        .src_access_mask(vk::AccessFlags::TRANSFER_WRITE)
-        .dst_access_mask(vk::AccessFlags::TRANSFER_READ)
-        .subresource_range(barrier_subresource_range);
-    unsafe {
-      device.cmd_pipeline_barrier(command_buffer,
-                                  vk::PipelineStageFlags::TRANSFER,
-                                  vk::PipelineStageFlags::TRANSFER,
-                                  vk::DependencyFlags::empty(),
-                                  &[] as &[vk::MemoryBarrier],
-                                  &[] as &[vk::BufferMemoryBarrier],
-                                  &[blit_barrier_info])
-    };
-
-    //   Now we do the actual blit. Nice and easy, though specifying the
-    // coordinates is a bit verbose.
-    let blit_source_layer_info = vk::ImageSubresourceLayers::builder()
-            .aspect_mask(vk::ImageAspectFlags::COLOR)
-            .mip_level(source_mip_level as u32)
-            .base_array_layer(0)
-            .layer_count(1);
-    let blit_destination_layer_info = vk::ImageSubresourceLayers::builder()
-            .aspect_mask(vk::ImageAspectFlags::COLOR)
-            .mip_level(destination_mip_level as u32)
-            .base_array_layer(0)
-            .layer_count(1);
-    let blit_info = vk::ImageBlit::builder()
-            .src_offsets([vk::Offset3D { x: 0, y: 0, z: 0 },
-                          vk::Offset3D {
-                            x: source_width as i32,
-                            y: source_height as i32,
-                            z: 1
-                          }])
-            .src_subresource(blit_source_layer_info)
-            .dst_offsets([vk::Offset3D { x: 0, y: 0, z: 0 },
-                          vk::Offset3D {
-                            x: destination_width as i32,
-                            y: destination_height as i32,
-                            z: 1
-                          }])
-            .dst_subresource(blit_destination_layer_info);
-    unsafe {
-      device.cmd_blit_image(command_buffer,
-                            *image, vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
-                            *image, vk::ImageLayout::TRANSFER_DST_OPTIMAL,
-                            &[blit_info],
-                            vk::Filter::LINEAR)
-    };
-
-    //   Now we do another pipeline_barrier. We're still acting on this
-    // iteration's source level, not on the destination. We'll never need to
-    // use it again except from the shader, so we set it appropriately for
-    // that.
-    blit_barrier_info = blit_barrier_info
-        .old_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL)
-        .new_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
-        .src_access_mask(vk::AccessFlags::TRANSFER_READ)
-        .dst_access_mask(vk::AccessFlags::SHADER_READ);
-    unsafe {
-      device.cmd_pipeline_barrier(command_buffer,
-                                  vk::PipelineStageFlags::TRANSFER,
-                                  vk::PipelineStageFlags::FRAGMENT_SHADER,
-                                  vk::DependencyFlags::empty(),
-                                  &[] as &[vk::MemoryBarrier],
-                                  &[] as &[vk::BufferMemoryBarrier],
-                                  &[blit_barrier_info])
-    };
-
-    source_width = destination_width;
-    source_height = destination_height;
-  }
-
-  let final_mip_level = mip_count - 1;
-
-  //   We need to do one final pipeline_barrier, because the loop didn't do it
-  // to the smallest (last) mip level. We change it to have the same settings
-  // the loop left the rest of them in. The barrier source properties for this
-  // barrier are different from the others because this level was never useds
-  // as a blit source, only as a blit destination. The barrier destination
-  // properties are the same as the rest, so after this all the subresourcess
-  // will be in their fully-ready state.
-  barrier_subresource_range = barrier_subresource_range
-      .base_mip_level(final_mip_level as u32);
-  blit_barrier_info = blit_barrier_info
-      .old_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
-      .new_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
-      .src_access_mask(vk::AccessFlags::TRANSFER_WRITE)
-      .dst_access_mask(vk::AccessFlags::SHADER_READ)
-      .subresource_range(barrier_subresource_range);
-  unsafe {
-    device.cmd_pipeline_barrier(command_buffer,
-                                vk::PipelineStageFlags::TRANSFER,
-                                vk::PipelineStageFlags::FRAGMENT_SHADER,
-                                vk::DependencyFlags::empty(),
-                                &[] as &[vk::MemoryBarrier],
-                                &[] as &[vk::BufferMemoryBarrier],
-                                &[blit_barrier_info])
-  };
-
-  end_transient_commands(command_buffer, device, queue, command_pool)?;
-
-  Ok(())
-}
-