unsafe fn generate_mipmaps_shader_ro_optimal(
    &self, graphics_command_buffer: vk::CommandBuffer, image: vk::Image, format: vk::Format,
    width: u32, height: u32, mip_levels: u32,
  ) -> SarektResult<()> {
    if mip_levels > 1 {
      // Check blitting supported.
      let format_properties = self
        .instance
        .get_physical_device_format_properties(self.physical_device, format);

      if !format_properties
        .optimal_tiling_features
        .intersects(vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_LINEAR)
      {
        return Err(SarektError::FormatDoesNotSupportMipmapping(format!(
          "Linear filtering not supported on format {:?}",
          format,
        )));
      }
    }

    let mut mip_width = width;
    let mut mip_height = height;
    for i in 1..mip_levels {
      // First transition previous image layout to transfer src optimal.
      let subresource_range = vk::ImageSubresourceRange::builder()
        .aspect_mask(vk::ImageAspectFlags::COLOR)
        .base_array_layer(0)
        .layer_count(1)
        .base_mip_level(i - 1)
        .level_count(1)
        .build();
      let barrier = [vk::ImageMemoryBarrier::builder()
        .image(image)
        .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
        .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
        .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(subresource_range)
        .build()];
      self.logical_device.cmd_pipeline_barrier(
        graphics_command_buffer,
        vk::PipelineStageFlags::TRANSFER,
        vk::PipelineStageFlags::TRANSFER,
        vk::DependencyFlags::empty(),
        &[],
        &[],
        &barrier,
      );

      // Then do the blit from one mip level to the next.
      let src_offsets = [
        vk::Offset3D::default(),
        vk::Offset3D::builder()
          .x(mip_width as i32)
          .y(mip_height as i32)
          .z(1)
          .build(),
      ];
      let src_subresource = vk::ImageSubresourceLayers::builder()
        .aspect_mask(vk::ImageAspectFlags::COLOR)
        .mip_level(i - 1)
        .base_array_layer(0)
        .layer_count(1)
        .build();
      let dst_offsets = [
        vk::Offset3D::default(),
        vk::Offset3D::builder()
          .x(if mip_width > 1 { mip_width / 2 } else { 1 } as i32)
          .y(if mip_height > 1 { mip_height / 2 } else { 1 } as i32)
          .z(1)
          .build(),
      ];
      let dst_subresource = vk::ImageSubresourceLayers::builder()
        .aspect_mask(vk::ImageAspectFlags::COLOR)
        .mip_level(i)
        .base_array_layer(0)
        .layer_count(1)
        .build();
      let blit = [vk::ImageBlit::builder()
        .src_offsets(src_offsets)
        .src_subresource(src_subresource)
        .dst_offsets(dst_offsets)
        .dst_subresource(dst_subresource)
        .build()];
      info!(
        "Generating mip level: {} {}x{}",
        i, dst_offsets[1].x, dst_offsets[1].y
      );
      self.logical_device.cmd_blit_image(
        graphics_command_buffer,
        image,
        vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
        image,
        vk::ImageLayout::TRANSFER_DST_OPTIMAL,
        &blit,
        vk::Filter::LINEAR,
      );

      // Now transition to shader ro optimal.
      let barrier = [vk::ImageMemoryBarrier::builder()
        .image(image)
        .subresource_range(subresource_range)
        .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
        .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
        .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)
        .build()];
      self.logical_device.cmd_pipeline_barrier(
        graphics_command_buffer,
        vk::PipelineStageFlags::TRANSFER,
        vk::PipelineStageFlags::FRAGMENT_SHADER,
        vk::DependencyFlags::empty(),
        &[],
        &[],
        &barrier,
      );

      if mip_width > 1 {
        mip_width /= 2;
      }
      if mip_height > 1 {
        mip_height /= 2;
      }
    }

    // Transition the final mip level to shader ro optimal (not handled by loop),
    // and transfer all queue ownership.
    let subresource_range = vk::ImageSubresourceRange::builder()
      .aspect_mask(vk::ImageAspectFlags::COLOR)
      .base_mip_level(mip_levels - 1)
      .level_count(1)
      .base_array_layer(0)
      .layer_count(1)
      .build();
    let barrier = [vk::ImageMemoryBarrier::builder()
      .image(image)
      .subresource_range(subresource_range)
      .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
      .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
      .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)
      .build()];
    info!("Transitioning final mip level to shader ro format");
    self.logical_device.cmd_pipeline_barrier(
      graphics_command_buffer,
      vk::PipelineStageFlags::TRANSFER,
      vk::PipelineStageFlags::FRAGMENT_SHADER,
      vk::DependencyFlags::empty(),
      &[],
      &[],
      &barrier,
    );

    Ok(())
  }
/// Use blitting to create mipmap textures.
/// Returns the source and destination queue family indices.
Use blitting to create mipmap textures.
Returns the source and destination queue family indices.
Use blitting to create mipmap textures . Returns the source and destination queue family indices .
unsafe fn generate_mipmaps_shader_ro_optimal(
    &self, graphics_command_buffer: vk::CommandBuffer, image: vk::Image, format: vk::Format,
    width: u32, height: u32, mip_levels: u32,
  ) -> SarektResult<()> {
    if mip_levels > 1 {
      // Check blitting supported.
      let format_properties = self
        .instance
        .get_physical_device_format_properties(self.physical_device, format);
      if !format_properties
        .optimal_tiling_features
        .intersects(vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_LINEAR)
      {
        return Err(SarektError::FormatDoesNotSupportMipmapping(format!(
          "Linear filtering not supported on format {:?}",
          format,
        )));
      }
    }
    let mut mip_width = width;
    let mut mip_height = height;
    for i in 1..mip_levels {
      // First transition previous image layout to transfer src optimal.
      let subresource_range = vk::ImageSubresourceRange::builder()
        .aspect_mask(vk::ImageAspectFlags::COLOR)
        .base_array_layer(0)
        .layer_count(1)
        .base_mip_level(i - 1)
        .level_count(1)
        .build();
      let barrier = [vk::ImageMemoryBarrier::builder()
        .image(image)
        .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
        .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
        .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(subresource_range)
        .build()];
      self.logical_device.cmd_pipeline_barrier(
        graphics_command_buffer,
        vk::PipelineStageFlags::TRANSFER,
        vk::PipelineStageFlags::TRANSFER,
        vk::DependencyFlags::empty(),
        &[],
        &[],
        &barrier,
      );
      // Then do the blit from one mip level to the next.
      let src_offsets = [
        vk::Offset3D::default(),
        vk::Offset3D::builder()
          .x(mip_width as i32)
          .y(mip_height as i32)
          .z(1)
          .build(),
      ];
      let src_subresource = vk::ImageSubresourceLayers::builder()
        .aspect_mask(vk::ImageAspectFlags::COLOR)
        .mip_level(i - 1)
        .base_array_layer(0)
        .layer_count(1)
        .build();
      let dst_offsets = [
        vk::Offset3D::default(),
        vk::Offset3D::builder()
          .x(if mip_width > 1 { mip_width / 2 } else { 1 } as i32)
          .y(if mip_height > 1 { mip_height / 2 } else { 1 } as i32)
          .z(1)
          .build(),
      ];
      let dst_subresource = vk::ImageSubresourceLayers::builder()
        .aspect_mask(vk::ImageAspectFlags::COLOR)
        .mip_level(i)
        .base_array_layer(0)
        .layer_count(1)
        .build();
      let blit = [vk::ImageBlit::builder()
        .src_offsets(src_offsets)
        .src_subresource(src_subresource)
        .dst_offsets(dst_offsets)
        .dst_subresource(dst_subresource)
        .build()];
      info!(
        "Generating mip level: {} {}x{}",
        i, dst_offsets[1].x, dst_offsets[1].y
      );
      self.logical_device.cmd_blit_image(
        graphics_command_buffer,
        image,
        vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
        image,
        vk::ImageLayout::TRANSFER_DST_OPTIMAL,
        &blit,
        vk::Filter::LINEAR,
      );
      // Now transition to shader ro optimal.
      let barrier = [vk::ImageMemoryBarrier::builder()
        .image(image)
        .subresource_range(subresource_range)
        .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
        .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
        .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)
        .build()];
      self.logical_device.cmd_pipeline_barrier(
        graphics_command_buffer,
        vk::PipelineStageFlags::TRANSFER,
        vk::PipelineStageFlags::FRAGMENT_SHADER,
        vk::DependencyFlags::empty(),
        &[],
        &[],
        &barrier,
      );
      if mip_width > 1 {
        mip_width /= 2;
      }
      if mip_height > 1 {
        mip_height /= 2;
      }
    }
    // Transition the final mip level to shader ro optimal (not handled by loop),
    // and transfer all queue ownership.
    let subresource_range = vk::ImageSubresourceRange::builder()
      .aspect_mask(vk::ImageAspectFlags::COLOR)
      .base_mip_level(mip_levels - 1)
      .level_count(1)
      .base_array_layer(0)
      .layer_count(1)
      .build();
    let barrier = [vk::ImageMemoryBarrier::builder()
      .image(image)
      .subresource_range(subresource_range)
      .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
      .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
      .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)
      .build()];
    info!("Transitioning final mip level to shader ro format");
    self.logical_device.cmd_pipeline_barrier(
      graphics_command_buffer,
      vk::PipelineStageFlags::TRANSFER,
      vk::PipelineStageFlags::FRAGMENT_SHADER,
      vk::DependencyFlags::empty(),
      &[],
      &[],
      &barrier,
    );
    Ok(())
  }
unsafe fn generate_mipmaps_shader_ro_optimal ( & self , graphics_command_buffer : vk :: CommandBuffer , image : vk :: Image , format : vk :: Format , width : u32 , height : u32 , mip_levels : u32 , ) -> SarektResult < ( ) > { if mip_levels > 1 { // Check blitting supported. let format_properties = self . instance . get_physical_device_format_properties ( self . physical_device , format ) ; if ! format_properties . optimal_tiling_features . intersects ( vk :: FormatFeatureFlags :: SAMPLED_IMAGE_FILTER_LINEAR ) { return Err ( SarektError :: FormatDoesNotSupportMipmapping ( format ! ( " " format ) ) ) ; } } let mut mip_width = width ; let mut mip_height = height ; for i in 1 .. mip_levels { // First transition previous image layout to transfer src optimal. let subresource_range = vk :: ImageSubresourceRange :: builder ( ) . aspect_mask ( vk :: ImageAspectFlags :: COLOR ) . base_array_layer ( 0 ) . layer_count ( 1 ) . base_mip_level ( i - 1 ) . level_count ( 1 ) . build ( ) ; let barrier = [ vk :: ImageMemoryBarrier :: builder ( ) . image ( image ) . src_queue_family_index ( vk :: QUEUE_FAMILY_IGNORED ) . dst_queue_family_index ( vk :: QUEUE_FAMILY_IGNORED ) . 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 ( subresource_range ) . build ( ) ] ; self . logical_device . cmd_pipeline_barrier ( graphics_command_buffer , vk :: PipelineStageFlags :: TRANSFER , vk :: PipelineStageFlags :: TRANSFER , vk :: DependencyFlags :: empty ( ) , & [ ] , & [ ] , & barrier , ) ; // Then do the blit from one mip level to the next. let src_offsets = [ vk :: Offset3D :: default ( ) , vk :: Offset3D :: builder ( ) . x ( mip_width as i32 ) . y ( mip_height as i32 ) . z ( 1 ) . build ( ) , ] ; let src_subresource = vk :: ImageSubresourceLayers :: builder ( ) . aspect_mask ( vk :: ImageAspectFlags :: COLOR ) . mip_level ( i - 1 ) . base_array_layer ( 0 ) . layer_count ( 1 ) . build ( ) ; let dst_offsets = [ vk :: Offset3D :: default ( ) , vk :: Offset3D :: builder ( ) . x ( if mip_width > 1 { mip_width / 2 } else { 1 } as i32 ) . y ( if mip_height > 1 { mip_height / 2 } else { 1 } as i32 ) . z ( 1 ) . build ( ) , ] ; let dst_subresource = vk :: ImageSubresourceLayers :: builder ( ) . aspect_mask ( vk :: ImageAspectFlags :: COLOR ) . mip_level ( i ) . base_array_layer ( 0 ) . layer_count ( 1 ) . build ( ) ; let blit = [ vk :: ImageBlit :: builder ( ) . src_offsets ( src_offsets ) . src_subresource ( src_subresource ) . dst_offsets ( dst_offsets ) . dst_subresource ( dst_subresource ) . build ( ) ] ; info ! ( " " i dst_offsets [ 1 ] x dst_offsets [ 1 ] y ) ; self . logical_device . cmd_blit_image ( graphics_command_buffer , image , vk :: ImageLayout :: TRANSFER_SRC_OPTIMAL , image , vk :: ImageLayout :: TRANSFER_DST_OPTIMAL , & blit , vk :: Filter :: LINEAR , ) ; // Now transition to shader ro optimal. let barrier = [ vk :: ImageMemoryBarrier :: builder ( ) . image ( image ) . subresource_range ( subresource_range ) . src_queue_family_index ( vk :: QUEUE_FAMILY_IGNORED ) . dst_queue_family_index ( vk :: QUEUE_FAMILY_IGNORED ) . 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 ) . build ( ) ] ; self . logical_device . cmd_pipeline_barrier ( graphics_command_buffer , vk :: PipelineStageFlags :: TRANSFER , vk :: PipelineStageFlags :: FRAGMENT_SHADER , vk :: DependencyFlags :: empty ( ) , & [ ] , & [ ] , & barrier , ) ; if mip_width > 1 { mip_width /= 2 ; } if mip_height > 1 { mip_height /= 2 ; } } // Transition the final mip level to shader ro optimal (not handled by loop), // and transfer all queue ownership. let subresource_range = vk :: ImageSubresourceRange :: builder ( ) . aspect_mask ( vk :: ImageAspectFlags :: COLOR ) . base_mip_level ( mip_levels - 1 ) . level_count ( 1 ) . base_array_layer ( 0 ) . layer_count ( 1 ) . build ( ) ; let barrier = [ vk :: ImageMemoryBarrier :: builder ( ) . image ( image ) . subresource_range ( subresource_range ) . src_queue_family_index ( vk :: QUEUE_FAMILY_IGNORED ) . dst_queue_family_index ( vk :: QUEUE_FAMILY_IGNORED ) . 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 ) . build ( ) ] ; info ! ( " " ) ; self . logical_device . cmd_pipeline_barrier ( graphics_command_buffer , vk :: PipelineStageFlags :: TRANSFER , vk :: PipelineStageFlags :: FRAGMENT_SHADER , vk :: DependencyFlags :: empty ( ) , & [ ] , & [ ] , & barrier , ) ; Ok ( ( ) ) }
Use blitting to create mipmap textures.
Use blitting to create mipmap textures .
&self
graphics_command_buffer
vk::CommandBuffer
image
vk::Image
format
vk::Format
width
u32
height
u32
mip_levels
u32
&self
graphics_command_buffer
vk::CommandBuffer
image
vk::Image
format
vk::Format
width
u32
height
u32
mip_levels
u32