From 71ddeee80c3ef38a2cc67c64bda1c30782da8985 Mon Sep 17 00:00:00 2001 From: hodasemi Date: Sun, 9 Mar 2025 07:49:15 +0100 Subject: [PATCH] Fix cube map mip-map-levels --- vulkan-rs/src/image.rs | 178 +++++++++++++++++++++++------------------ 1 file changed, 98 insertions(+), 80 deletions(-) diff --git a/vulkan-rs/src/image.rs b/vulkan-rs/src/image.rs index 9d40c43..800dfdc 100644 --- a/vulkan-rs/src/image.rs +++ b/vulkan-rs/src/image.rs @@ -381,6 +381,22 @@ impl ImageBuilder { info.vk_image_create_info.extent.height, ); + self.mip_map_levels(levels) + } + _ => panic!("wrong builder type in ImageBuilder"), + } + } + + pub fn mip_map_levels(mut self, levels: u32) -> Self { + match self.builder_type { + ImageBuilderInternalType::NewImage(ref mut info) => { + let max_levels = Self::calc_mip_map_levels( + info.vk_image_create_info.extent.width, + info.vk_image_create_info.extent.height, + ); + + debug_assert!(levels <= max_levels, "too many mip maps levels"); + info.vk_image_create_info.mipLevels = levels; self.subresource_range.levelCount = levels; @@ -1276,90 +1292,92 @@ fn blit_mip_maps( image: &Arc, target_image_layout: VkImageLayout, ) { - let mut mip_width = image.width(); - let mut mip_height = image.height(); - - // subresource information - let mut subresource_range = VkImageSubresourceRange { - aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(), - baseMipLevel: 0, - levelCount: 1, - baseArrayLayer: 0, - layerCount: image.layers(), - }; - - for i in 1..image.levels() { - let source_mip_level = i - 1; - let target_mip_level = i; - - // transition the previous mip level from destination to source - subresource_range.baseMipLevel = source_mip_level; - buffer_recorder.set_image_layout( - image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresource_range.clone(), - ); - - // create the blit information to blit the data from one mip level to another - let image_blit = VkImageBlit { - srcSubresource: VkImageSubresourceLayers { - aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(), - mipLevel: source_mip_level, - baseArrayLayer: 0, - layerCount: 1, - }, - srcOffsets: [ - VkOffset3D { x: 0, y: 0, z: 0 }, - VkOffset3D { - x: mip_width as i32, - y: mip_height as i32, - z: 1, - }, - ], - dstSubresource: VkImageSubresourceLayers { - aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(), - mipLevel: target_mip_level, - baseArrayLayer: 0, - layerCount: 1, - }, - dstOffsets: [ - VkOffset3D { x: 0, y: 0, z: 0 }, - VkOffset3D { - x: if mip_width > 1 { - mip_width as i32 / 2 - } else { - 1 - }, - y: if mip_height > 1 { - mip_height as i32 / 2 - } else { - 1 - }, - z: 1, - }, - ], + for layer in 0..image.layers() { + // subresource information + let mut subresource_range = VkImageSubresourceRange { + aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(), + baseMipLevel: 0, + levelCount: 1, + baseArrayLayer: layer, + layerCount: image.layers(), }; - // execute the actual blit - buffer_recorder.blit_image( - image, - image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - &[image_blit], - VK_FILTER_LINEAR, - ); + let mut mip_width = image.width(); + let mut mip_height = image.height(); - // set mip level i - 1 to target layout - buffer_recorder.set_image_layout(image, target_image_layout, subresource_range.clone()); + for i in 1..image.levels() { + let source_mip_level = i - 1; + let target_mip_level = i; - image.set_image_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + // transition the previous mip level from destination to source + subresource_range.baseMipLevel = source_mip_level; + buffer_recorder.set_image_layout( + image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + subresource_range.clone(), + ); - mip_width = if mip_width > 1 { mip_width / 2 } else { 1 }; - mip_height = if mip_height > 1 { mip_height / 2 } else { 1 }; + // create the blit information to blit the data from one mip level to another + let image_blit = VkImageBlit { + srcSubresource: VkImageSubresourceLayers { + aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(), + mipLevel: source_mip_level, + baseArrayLayer: layer, + layerCount: 1, + }, + srcOffsets: [ + VkOffset3D { x: 0, y: 0, z: 0 }, + VkOffset3D { + x: mip_width as i32, + y: mip_height as i32, + z: 1, + }, + ], + dstSubresource: VkImageSubresourceLayers { + aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(), + mipLevel: target_mip_level, + baseArrayLayer: layer, + layerCount: 1, + }, + dstOffsets: [ + VkOffset3D { x: 0, y: 0, z: 0 }, + VkOffset3D { + x: if mip_width > 1 { + mip_width as i32 / 2 + } else { + 1 + }, + y: if mip_height > 1 { + mip_height as i32 / 2 + } else { + 1 + }, + z: 1, + }, + ], + }; + + // execute the actual blit + buffer_recorder.blit_image( + image, + image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &[image_blit], + VK_FILTER_LINEAR, + ); + + // set mip level i - 1 to target layout + buffer_recorder.set_image_layout(image, target_image_layout, subresource_range.clone()); + + image.set_image_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + mip_width = if mip_width > 1 { mip_width / 2 } else { 1 }; + mip_height = if mip_height > 1 { mip_height / 2 } else { 1 }; + } + + // set last level to be target layout + subresource_range.baseMipLevel = image.levels() - 1; + buffer_recorder.set_image_layout(image, target_image_layout, subresource_range); } - - // set last level to be target layout - subresource_range.baseMipLevel = image.levels() - 1; - buffer_recorder.set_image_layout(image, target_image_layout, subresource_range); }