Add to_file function for image
This commit is contained in:
parent
530f0d4e03
commit
69ec318579
1 changed files with 83 additions and 0 deletions
|
@ -5,6 +5,7 @@ use crate::prelude::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
use std::path::Path;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -776,6 +777,88 @@ impl Image {
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL => VK_ACCESS_SHADER_READ_BIT.into(),
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL => VK_ACCESS_SHADER_READ_BIT.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_file(self: &Arc<Image>, path: impl AsRef<Path>) -> Result<()> {
|
||||||
|
let buffer = self.copy_image_to_buffer()?;
|
||||||
|
let memory = buffer.map_complete()?;
|
||||||
|
|
||||||
|
let image = image::RgbaImage::from_raw(
|
||||||
|
self.width,
|
||||||
|
self.height,
|
||||||
|
memory.iter().map(|&v| v).collect(),
|
||||||
|
)
|
||||||
|
.ok_or(anyhow::anyhow!(
|
||||||
|
"failed to create image from raw while saving to file: {:?}",
|
||||||
|
path.as_ref()
|
||||||
|
))?;
|
||||||
|
|
||||||
|
image.save(path)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy_image_to_buffer(self: &Arc<Image>) -> Result<Arc<Buffer<u8>>> {
|
||||||
|
let buffer = Buffer::builder()
|
||||||
|
.set_usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||||
|
.set_memory_usage(MemoryUsage::GpuToCpu)
|
||||||
|
.set_size((self.width * self.height * 4) as VkDeviceSize)
|
||||||
|
.build(self.device.clone())?;
|
||||||
|
|
||||||
|
let command_buffer =
|
||||||
|
CommandBuffer::new_primary().build(self.device.clone(), self.queue.clone())?;
|
||||||
|
|
||||||
|
SingleSubmit::builder(&command_buffer, &self.queue, |recorder| {
|
||||||
|
// copy info for copying the content of the buffer into the image
|
||||||
|
let buffer_image_copy = VkBufferImageCopy {
|
||||||
|
bufferOffset: 0,
|
||||||
|
bufferRowLength: 0,
|
||||||
|
bufferImageHeight: 0,
|
||||||
|
imageSubresource: VkImageSubresourceLayers {
|
||||||
|
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(),
|
||||||
|
mipLevel: 0,
|
||||||
|
baseArrayLayer: 0,
|
||||||
|
layerCount: 1,
|
||||||
|
},
|
||||||
|
imageOffset: VkOffset3D { x: 0, y: 0, z: 0 },
|
||||||
|
imageExtent: VkExtent3D {
|
||||||
|
width: self.width(),
|
||||||
|
height: self.height(),
|
||||||
|
depth: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// subresource information
|
||||||
|
let subresource_range = VkImageSubresourceRange {
|
||||||
|
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(),
|
||||||
|
baseMipLevel: 0,
|
||||||
|
levelCount: 1,
|
||||||
|
baseArrayLayer: 0,
|
||||||
|
layerCount: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let current_layout = self.image_layout();
|
||||||
|
|
||||||
|
recorder.set_image_layout(
|
||||||
|
self,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
subresource_range.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
recorder.copy_image_to_buffer(
|
||||||
|
self,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
&buffer,
|
||||||
|
&[buffer_image_copy],
|
||||||
|
);
|
||||||
|
|
||||||
|
recorder.set_image_layout(self, current_layout, subresource_range);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.submit()?;
|
||||||
|
|
||||||
|
Ok(buffer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanDevice for Image {
|
impl VulkanDevice for Image {
|
||||||
|
|
Loading…
Reference in a new issue