Fix cube map mip-map-levels

This commit is contained in:
hodasemi 2025-03-09 07:49:15 +01:00
parent e76d35d8d5
commit 71ddeee80c

View file

@ -381,6 +381,22 @@ impl ImageBuilder {
info.vk_image_create_info.extent.height, 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; info.vk_image_create_info.mipLevels = levels;
self.subresource_range.levelCount = levels; self.subresource_range.levelCount = levels;
@ -1276,90 +1292,92 @@ fn blit_mip_maps(
image: &Arc<Image>, image: &Arc<Image>,
target_image_layout: VkImageLayout, target_image_layout: VkImageLayout,
) { ) {
let mut mip_width = image.width(); for layer in 0..image.layers() {
let mut mip_height = image.height(); // subresource information
let mut subresource_range = VkImageSubresourceRange {
// subresource information aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(),
let mut subresource_range = VkImageSubresourceRange { baseMipLevel: 0,
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(), levelCount: 1,
baseMipLevel: 0, baseArrayLayer: layer,
levelCount: 1, layerCount: image.layers(),
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,
},
],
}; };
// execute the actual blit let mut mip_width = image.width();
buffer_recorder.blit_image( let mut mip_height = image.height();
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 for i in 1..image.levels() {
buffer_recorder.set_image_layout(image, target_image_layout, subresource_range.clone()); 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 }; // create the blit information to blit the data from one mip level to another
mip_height = if mip_height > 1 { mip_height / 2 } else { 1 }; 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);
} }