From 3e453a817005708f6eb6587b670760810fb2dc05 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Fri, 14 Apr 2023 10:21:26 -0400 Subject: [PATCH] Complete section 28 --- src/app/data.rs | 115 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/src/app/data.rs b/src/app/data.rs index a9afaad..4e09966 100644 --- a/src/app/data.rs +++ b/src/app/data.rs @@ -231,6 +231,8 @@ impl AppData { /// Here be Dragons pub unsafe fn destroy(&mut self, instance: &Instance, device: &Device) { self.destroy_swapchain(device); + device.destroy_image(self.texture_image, None); + device.free_memory(self.texture_image_memory, None); device.destroy_descriptor_set_layout(self.descriptor_set_layout, None); device.destroy_buffer(self.index_buffer, None); @@ -684,6 +686,7 @@ impl AppData { //================================================ fn create_texture_image(&mut self, instance: &Instance, device: &Device) -> Result<()> { + // Load the image let image = File::open("resources/texture.png")?; let decoder = png::Decoder::new(image); @@ -695,7 +698,8 @@ impl AppData { let size = reader.info().raw_bytes() as u64; let (width, height) = reader.info().size(); - let (_, staging_buffer_memory) = unsafe { + // Create the staging buffer + let (staging_buffer, staging_buffer_memory) = unsafe { self.create_buffer( instance, device, @@ -727,6 +731,27 @@ impl AppData { self.texture_image = texture_image; self.texture_image_memory = texture_image_memory; + + self.transition_image_layout( + device, + self.texture_image, + vk::Format::R8G8B8A8_SRGB, + vk::ImageLayout::UNDEFINED, + vk::ImageLayout::TRANSFER_DST_OPTIMAL, + )?; + + self.copy_buffer_to_image(device, staging_buffer, self.texture_image, width, height)?; + + self.transition_image_layout( + device, + self.texture_image, + vk::Format::R8G8B8A8_SRGB, + vk::ImageLayout::TRANSFER_DST_OPTIMAL, + vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, + )?; + + device.destroy_buffer(staging_buffer, None); + device.free_memory(staging_buffer_memory, None); } Ok(()) @@ -1079,8 +1104,96 @@ impl AppData { old_layout: vk::ImageLayout, new_layout: vk::ImageLayout, ) -> Result<()> { + let (src_access_mask, dst_access_mask, src_stage_mask, dst_stage_mask) = + match (old_layout, new_layout) { + (vk::ImageLayout::UNDEFINED, vk::ImageLayout::TRANSFER_DST_OPTIMAL) => ( + vk::AccessFlags::empty(), + vk::AccessFlags::TRANSFER_WRITE, + vk::PipelineStageFlags::TOP_OF_PIPE, + vk::PipelineStageFlags::TRANSFER, + ), + ( + vk::ImageLayout::TRANSFER_DST_OPTIMAL, + vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, + ) => ( + vk::AccessFlags::TRANSFER_WRITE, + vk::AccessFlags::SHADER_READ, + vk::PipelineStageFlags::TRANSFER, + vk::PipelineStageFlags::FRAGMENT_SHADER, + ), + _ => return Err(anyhow!("Unsupported image layout transition!")), + }; + let command_buffer = self.begin_single_time_commands(device)?; + let subresource = vk::ImageSubresourceRange::builder() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .base_mip_level(0) + .level_count(1) + .base_array_layer(0) + .layer_count(1); + + let barrier = vk::ImageMemoryBarrier::builder() + .old_layout(old_layout) + .new_layout(new_layout) + .src_queue_family_index(vk::QUEUE_FAMILY_IGNORED) + .dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED) + .image(image) + .subresource_range(subresource) + .src_access_mask(src_access_mask) + .dst_access_mask(dst_access_mask); + + device.cmd_pipeline_barrier( + command_buffer, + src_stage_mask, + dst_stage_mask, + vk::DependencyFlags::empty(), + &[] as &[vk::MemoryBarrier], + &[] as &[vk::BufferMemoryBarrier], + &[barrier], + ); + + self.end_single_time_commands(device, command_buffer)?; + + Ok(()) + } + + unsafe fn copy_buffer_to_image( + &self, + device: &Device, + buffer: vk::Buffer, + image: vk::Image, + width: u32, + height: u32, + ) -> Result<()> { + let command_buffer = self.begin_single_time_commands(device)?; + + let subresource = vk::ImageSubresourceLayers::builder() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .mip_level(0) + .base_array_layer(0) + .layer_count(1); + + let region = vk::BufferImageCopy::builder() + .buffer_offset(0) + .buffer_row_length(0) + .buffer_image_height(0) + .image_subresource(subresource) + .image_offset(vk::Offset3D { x: 0, y: 0, z: 0 }) + .image_extent(vk::Extent3D { + width, + height, + depth: 1, + }); + + device.cmd_copy_buffer_to_image( + command_buffer, + buffer, + image, + vk::ImageLayout::TRANSFER_DST_OPTIMAL, + &[region], + ); + self.end_single_time_commands(device, command_buffer)?; Ok(())