Add first cube map implementation
This commit is contained in:
parent
c650dcd1e0
commit
5ffc55b416
1 changed files with 107 additions and 28 deletions
|
@ -13,6 +13,7 @@ enum ImageSourceType {
|
|||
Empty,
|
||||
Raw(Vec<u8>),
|
||||
Array(Vec<Arc<Image>>),
|
||||
CubeMap([Vec<u8>; 6]),
|
||||
}
|
||||
|
||||
struct ImageCreateInfo {
|
||||
|
@ -144,25 +145,25 @@ impl ImageBuilder {
|
|||
Ok(image)
|
||||
}
|
||||
ImageBuilderInternalType::NewImage(info) => match info.source_type {
|
||||
ImageSourceType::Array(ref array) => {
|
||||
ImageSourceType::Array(array) => {
|
||||
let arc_image = Self::create_from_source(
|
||||
device,
|
||||
queue,
|
||||
&info,
|
||||
info.vk_image_create_info,
|
||||
self.sampler,
|
||||
image_view_ci,
|
||||
self.file_name,
|
||||
)?;
|
||||
|
||||
copy_images_to_imagearray(device, queue, &arc_image, array)?;
|
||||
copy_images_to_image_array(device, queue, &arc_image, &array)?;
|
||||
|
||||
Ok(arc_image)
|
||||
}
|
||||
ImageSourceType::Raw(ref raw) => {
|
||||
ImageSourceType::Raw(raw) => {
|
||||
let arc_image = Self::create_from_source(
|
||||
device,
|
||||
queue,
|
||||
&info,
|
||||
info.vk_image_create_info,
|
||||
self.sampler,
|
||||
image_view_ci,
|
||||
self.file_name,
|
||||
|
@ -172,9 +173,10 @@ impl ImageBuilder {
|
|||
device,
|
||||
queue,
|
||||
&raw.into_iter()
|
||||
.map(|&d| RawBuffer { d })
|
||||
.map(|d| RawBuffer { d })
|
||||
.collect::<Vec<RawBuffer>>(),
|
||||
&arc_image,
|
||||
0,
|
||||
)?;
|
||||
|
||||
Ok(arc_image)
|
||||
|
@ -183,12 +185,36 @@ impl ImageBuilder {
|
|||
let arc_image = Self::create_from_source(
|
||||
device,
|
||||
queue,
|
||||
&info,
|
||||
info.vk_image_create_info,
|
||||
self.sampler,
|
||||
image_view_ci,
|
||||
self.file_name,
|
||||
)?;
|
||||
|
||||
Ok(arc_image)
|
||||
}
|
||||
ImageSourceType::CubeMap(raw_array) => {
|
||||
let arc_image = Self::create_from_source(
|
||||
device,
|
||||
queue,
|
||||
info.vk_image_create_info,
|
||||
self.sampler,
|
||||
image_view_ci,
|
||||
self.file_name,
|
||||
)?;
|
||||
|
||||
for (layer, raw) in raw_array.into_iter().enumerate() {
|
||||
Self::optimize_fill(
|
||||
device,
|
||||
queue,
|
||||
&raw.into_iter()
|
||||
.map(|d| RawBuffer { d })
|
||||
.collect::<Vec<RawBuffer>>(),
|
||||
&arc_image,
|
||||
layer as u32,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(arc_image)
|
||||
}
|
||||
},
|
||||
|
@ -357,6 +383,10 @@ impl ImageBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn get_lod(&self) -> f32 {
|
||||
self.subresource_range.levelCount as f32
|
||||
}
|
||||
|
||||
pub fn aspect_mask(mut self, mask: VkImageAspectFlags) -> Self {
|
||||
self.subresource_range.aspectMask = mask.into();
|
||||
|
||||
|
@ -386,14 +416,14 @@ impl ImageBuilder {
|
|||
fn create_from_source(
|
||||
device: &Arc<Device>,
|
||||
queue: &Arc<Mutex<Queue>>,
|
||||
info: &ImageCreateInfo,
|
||||
info: VkImageCreateInfo,
|
||||
sampler: Option<Arc<Sampler>>,
|
||||
mut view_ci: VkImageViewCreateInfo,
|
||||
file_name: Option<AssetPath>,
|
||||
) -> Result<Arc<Image>> {
|
||||
let format = view_ci.format;
|
||||
|
||||
let (image, memory) = Self::create_texture(device, &info.vk_image_create_info)?;
|
||||
let (image, memory) = Self::create_texture(device, &info)?;
|
||||
|
||||
view_ci.image = image;
|
||||
|
||||
|
@ -412,16 +442,16 @@ impl ImageBuilder {
|
|||
file_name,
|
||||
|
||||
format,
|
||||
image_layout: Mutex::new(info.vk_image_create_info.initialLayout),
|
||||
image_layout: Mutex::new(info.initialLayout),
|
||||
|
||||
aspect_mask: view_ci.subresourceRange.aspectMask,
|
||||
|
||||
width: info.vk_image_create_info.extent.width,
|
||||
height: info.vk_image_create_info.extent.height,
|
||||
layers: info.vk_image_create_info.arrayLayers,
|
||||
levels: info.vk_image_create_info.mipLevels,
|
||||
sample_count: info.vk_image_create_info.samples,
|
||||
usage: info.vk_image_create_info.usage,
|
||||
width: info.extent.width,
|
||||
height: info.extent.height,
|
||||
layers: info.arrayLayers,
|
||||
levels: info.mipLevels,
|
||||
sample_count: info.samples,
|
||||
usage: info.usage,
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -430,11 +460,7 @@ impl ImageBuilder {
|
|||
image_ci: &VkImageCreateInfo,
|
||||
) -> Result<(VkImage, Arc<Memory<RawBuffer>>)> {
|
||||
let image = Self::create_image(device, image_ci)?;
|
||||
let memory = Memory::image_memory(
|
||||
device,
|
||||
image,
|
||||
MemoryUsage::into_vma(Some(MemoryUsage::GpuOnly)),
|
||||
)?;
|
||||
let memory = Memory::image_memory(device, image, MemoryUsage::GpuOnly.into())?;
|
||||
|
||||
Ok((image, memory))
|
||||
}
|
||||
|
@ -451,6 +477,7 @@ impl ImageBuilder {
|
|||
queue: &Arc<Mutex<Queue>>,
|
||||
data: &[RawBuffer],
|
||||
image: &Arc<Image>,
|
||||
layer: u32,
|
||||
) -> Result<()> {
|
||||
let staging_buffer = Buffer::builder()
|
||||
.set_usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
|
||||
|
@ -458,7 +485,7 @@ impl ImageBuilder {
|
|||
.set_data(data)
|
||||
.build(device.clone())?;
|
||||
|
||||
copy_buffer_to_image(device, queue, &staging_buffer, image)?;
|
||||
copy_buffer_to_image(device, queue, &staging_buffer, image, layer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -624,7 +651,6 @@ impl Image {
|
|||
let array_len = array.len() as u32;
|
||||
let mut create_info = ImageCreateInfo::default(ImageSourceType::Array(array));
|
||||
create_info.vk_image_create_info.arrayLayers = array_len;
|
||||
create_info.vk_image_create_info.imageType = VK_IMAGE_TYPE_2D;
|
||||
create_info.vk_image_create_info.extent.width = width;
|
||||
create_info.vk_image_create_info.extent.height = height;
|
||||
create_info.vk_image_create_info.extent.depth = 1;
|
||||
|
@ -636,6 +662,56 @@ impl Image {
|
|||
image_builder
|
||||
}
|
||||
|
||||
/// Creates an `ImageBuilder` where you can define the image for your needs
|
||||
///
|
||||
/// takes an array of 6 files and setups the `ImageBuilder` to create
|
||||
/// a single `Arc<Image>` with an cube map image created from the provided files
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `array` - Source images
|
||||
pub fn cube_map(array: [AssetPath; 6]) -> Result<ImageBuilder> {
|
||||
let images = array
|
||||
.into_iter()
|
||||
.map(|path| {
|
||||
image::open(&path.full_path())
|
||||
.map(|i| i.to_rgba8())
|
||||
.map_err(|err| anyhow::Error::new(err).context(path.full_path()))
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let width = images[0].width();
|
||||
let height = images[0].height();
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
for image in &images {
|
||||
if width != image.width() || height != image.height() {
|
||||
panic!("images are not equally sized");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut create_info = ImageCreateInfo::default(ImageSourceType::CubeMap(
|
||||
images
|
||||
.into_iter()
|
||||
.map(|image| image.into_raw())
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
));
|
||||
create_info.vk_image_create_info.arrayLayers = 6;
|
||||
create_info.vk_image_create_info.extent.width = width;
|
||||
create_info.vk_image_create_info.extent.height = height;
|
||||
create_info.vk_image_create_info.extent.depth = 1;
|
||||
create_info.vk_image_create_info.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT.into();
|
||||
|
||||
let mut image_builder = ImageBuilder::new(ImageBuilderInternalType::NewImage(create_info));
|
||||
image_builder.view_type = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
image_builder.subresource_range.layerCount = 6;
|
||||
|
||||
Ok(image_builder)
|
||||
}
|
||||
|
||||
/// Creates an `ImageBuilder` where you can define the image for your needs
|
||||
///
|
||||
/// takes raw information to setup `ImageBuilder`, that creates an `Arc<Image>`
|
||||
|
@ -789,7 +865,7 @@ impl Image {
|
|||
}
|
||||
|
||||
pub fn to_file(self: &Arc<Image>, path: impl AsRef<Path>) -> Result<()> {
|
||||
// check if image is created with correct usage flag that allows transfering data from it
|
||||
// check if image is created with correct usage flag that allows transferring data from it
|
||||
if (self.usage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) == 0 {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Image has not been create with VK_IMAGE_USAGE_TRANSFER_SRC_BIT flag!"
|
||||
|
@ -886,7 +962,7 @@ impl Image {
|
|||
}
|
||||
|
||||
pub fn copy_buffer_to_image(self: &Arc<Image>, buffer: &Arc<Buffer<RawBuffer>>) -> Result<()> {
|
||||
copy_buffer_to_image(&self.device, &self.queue, &buffer, self)
|
||||
copy_buffer_to_image(&self.device, &self.queue, &buffer, self, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -955,10 +1031,13 @@ fn copy_buffer_to_image<T: ReprC + Send + Sync + 'static>(
|
|||
queue: &Arc<Mutex<Queue>>,
|
||||
buffer: &Arc<Buffer<T>>,
|
||||
image: &Arc<Image>,
|
||||
layer: u32,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
debug_assert!(layer < image.layers);
|
||||
|
||||
// create a new command buffer
|
||||
let command_buffer = CommandBuffer::new_primary().build(device.clone(), queue.clone())?;
|
||||
|
||||
|
@ -976,7 +1055,7 @@ where
|
|||
imageSubresource: VkImageSubresourceLayers {
|
||||
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(),
|
||||
mipLevel: 0,
|
||||
baseArrayLayer: 0,
|
||||
baseArrayLayer: layer,
|
||||
layerCount: 1,
|
||||
},
|
||||
imageOffset: VkOffset3D { x: 0, y: 0, z: 0 },
|
||||
|
@ -993,7 +1072,7 @@ where
|
|||
baseMipLevel: 0,
|
||||
levelCount: image.levels(),
|
||||
baseArrayLayer: 0,
|
||||
layerCount: 1,
|
||||
layerCount: image.layers(),
|
||||
};
|
||||
|
||||
// set image layout to receive content
|
||||
|
@ -1045,7 +1124,7 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_images_to_imagearray(
|
||||
fn copy_images_to_image_array(
|
||||
device: &Arc<Device>,
|
||||
queue: &Arc<Mutex<Queue>>,
|
||||
image_array: &Arc<Image>,
|
||||
|
|
Loading…
Reference in a new issue