Add first cube map implementation

This commit is contained in:
hodasemi 2025-02-28 14:45:43 +01:00
parent c650dcd1e0
commit 5ffc55b416

View file

@ -13,6 +13,7 @@ enum ImageSourceType {
Empty, Empty,
Raw(Vec<u8>), Raw(Vec<u8>),
Array(Vec<Arc<Image>>), Array(Vec<Arc<Image>>),
CubeMap([Vec<u8>; 6]),
} }
struct ImageCreateInfo { struct ImageCreateInfo {
@ -144,25 +145,25 @@ impl ImageBuilder {
Ok(image) Ok(image)
} }
ImageBuilderInternalType::NewImage(info) => match info.source_type { ImageBuilderInternalType::NewImage(info) => match info.source_type {
ImageSourceType::Array(ref array) => { ImageSourceType::Array(array) => {
let arc_image = Self::create_from_source( let arc_image = Self::create_from_source(
device, device,
queue, queue,
&info, info.vk_image_create_info,
self.sampler, self.sampler,
image_view_ci, image_view_ci,
self.file_name, 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) Ok(arc_image)
} }
ImageSourceType::Raw(ref raw) => { ImageSourceType::Raw(raw) => {
let arc_image = Self::create_from_source( let arc_image = Self::create_from_source(
device, device,
queue, queue,
&info, info.vk_image_create_info,
self.sampler, self.sampler,
image_view_ci, image_view_ci,
self.file_name, self.file_name,
@ -172,9 +173,10 @@ impl ImageBuilder {
device, device,
queue, queue,
&raw.into_iter() &raw.into_iter()
.map(|&d| RawBuffer { d }) .map(|d| RawBuffer { d })
.collect::<Vec<RawBuffer>>(), .collect::<Vec<RawBuffer>>(),
&arc_image, &arc_image,
0,
)?; )?;
Ok(arc_image) Ok(arc_image)
@ -183,12 +185,36 @@ impl ImageBuilder {
let arc_image = Self::create_from_source( let arc_image = Self::create_from_source(
device, device,
queue, queue,
&info, info.vk_image_create_info,
self.sampler, self.sampler,
image_view_ci, image_view_ci,
self.file_name, 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) Ok(arc_image)
} }
}, },
@ -357,6 +383,10 @@ impl ImageBuilder {
self self
} }
pub fn get_lod(&self) -> f32 {
self.subresource_range.levelCount as f32
}
pub fn aspect_mask(mut self, mask: VkImageAspectFlags) -> Self { pub fn aspect_mask(mut self, mask: VkImageAspectFlags) -> Self {
self.subresource_range.aspectMask = mask.into(); self.subresource_range.aspectMask = mask.into();
@ -386,14 +416,14 @@ impl ImageBuilder {
fn create_from_source( fn create_from_source(
device: &Arc<Device>, device: &Arc<Device>,
queue: &Arc<Mutex<Queue>>, queue: &Arc<Mutex<Queue>>,
info: &ImageCreateInfo, info: VkImageCreateInfo,
sampler: Option<Arc<Sampler>>, sampler: Option<Arc<Sampler>>,
mut view_ci: VkImageViewCreateInfo, mut view_ci: VkImageViewCreateInfo,
file_name: Option<AssetPath>, file_name: Option<AssetPath>,
) -> Result<Arc<Image>> { ) -> Result<Arc<Image>> {
let format = view_ci.format; 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; view_ci.image = image;
@ -412,16 +442,16 @@ impl ImageBuilder {
file_name, file_name,
format, format,
image_layout: Mutex::new(info.vk_image_create_info.initialLayout), image_layout: Mutex::new(info.initialLayout),
aspect_mask: view_ci.subresourceRange.aspectMask, aspect_mask: view_ci.subresourceRange.aspectMask,
width: info.vk_image_create_info.extent.width, width: info.extent.width,
height: info.vk_image_create_info.extent.height, height: info.extent.height,
layers: info.vk_image_create_info.arrayLayers, layers: info.arrayLayers,
levels: info.vk_image_create_info.mipLevels, levels: info.mipLevels,
sample_count: info.vk_image_create_info.samples, sample_count: info.samples,
usage: info.vk_image_create_info.usage, usage: info.usage,
})) }))
} }
@ -430,11 +460,7 @@ impl ImageBuilder {
image_ci: &VkImageCreateInfo, image_ci: &VkImageCreateInfo,
) -> Result<(VkImage, Arc<Memory<RawBuffer>>)> { ) -> Result<(VkImage, Arc<Memory<RawBuffer>>)> {
let image = Self::create_image(device, image_ci)?; let image = Self::create_image(device, image_ci)?;
let memory = Memory::image_memory( let memory = Memory::image_memory(device, image, MemoryUsage::GpuOnly.into())?;
device,
image,
MemoryUsage::into_vma(Some(MemoryUsage::GpuOnly)),
)?;
Ok((image, memory)) Ok((image, memory))
} }
@ -451,6 +477,7 @@ impl ImageBuilder {
queue: &Arc<Mutex<Queue>>, queue: &Arc<Mutex<Queue>>,
data: &[RawBuffer], data: &[RawBuffer],
image: &Arc<Image>, image: &Arc<Image>,
layer: u32,
) -> Result<()> { ) -> Result<()> {
let staging_buffer = Buffer::builder() let staging_buffer = Buffer::builder()
.set_usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT) .set_usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
@ -458,7 +485,7 @@ impl ImageBuilder {
.set_data(data) .set_data(data)
.build(device.clone())?; .build(device.clone())?;
copy_buffer_to_image(device, queue, &staging_buffer, image)?; copy_buffer_to_image(device, queue, &staging_buffer, image, layer)?;
Ok(()) Ok(())
} }
@ -624,7 +651,6 @@ impl Image {
let array_len = array.len() as u32; let array_len = array.len() as u32;
let mut create_info = ImageCreateInfo::default(ImageSourceType::Array(array)); let mut create_info = ImageCreateInfo::default(ImageSourceType::Array(array));
create_info.vk_image_create_info.arrayLayers = array_len; 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.width = width;
create_info.vk_image_create_info.extent.height = height; create_info.vk_image_create_info.extent.height = height;
create_info.vk_image_create_info.extent.depth = 1; create_info.vk_image_create_info.extent.depth = 1;
@ -636,6 +662,56 @@ impl Image {
image_builder 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 /// Creates an `ImageBuilder` where you can define the image for your needs
/// ///
/// takes raw information to setup `ImageBuilder`, that creates an `Arc<Image>` /// 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<()> { 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 { if (self.usage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) == 0 {
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
"Image has not been create with VK_IMAGE_USAGE_TRANSFER_SRC_BIT flag!" "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<()> { 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>>, queue: &Arc<Mutex<Queue>>,
buffer: &Arc<Buffer<T>>, buffer: &Arc<Buffer<T>>,
image: &Arc<Image>, image: &Arc<Image>,
layer: u32,
) -> Result<()> ) -> Result<()>
where where
T: Copy, T: Copy,
{ {
debug_assert!(layer < image.layers);
// create a new command buffer // create a new command buffer
let command_buffer = CommandBuffer::new_primary().build(device.clone(), queue.clone())?; let command_buffer = CommandBuffer::new_primary().build(device.clone(), queue.clone())?;
@ -976,7 +1055,7 @@ where
imageSubresource: VkImageSubresourceLayers { imageSubresource: VkImageSubresourceLayers {
aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(), aspectMask: VK_IMAGE_ASPECT_COLOR_BIT.into(),
mipLevel: 0, mipLevel: 0,
baseArrayLayer: 0, baseArrayLayer: layer,
layerCount: 1, layerCount: 1,
}, },
imageOffset: VkOffset3D { x: 0, y: 0, z: 0 }, imageOffset: VkOffset3D { x: 0, y: 0, z: 0 },
@ -993,7 +1072,7 @@ where
baseMipLevel: 0, baseMipLevel: 0,
levelCount: image.levels(), levelCount: image.levels(),
baseArrayLayer: 0, baseArrayLayer: 0,
layerCount: 1, layerCount: image.layers(),
}; };
// set image layout to receive content // set image layout to receive content
@ -1045,7 +1124,7 @@ where
Ok(()) Ok(())
} }
fn copy_images_to_imagearray( fn copy_images_to_image_array(
device: &Arc<Device>, device: &Arc<Device>,
queue: &Arc<Mutex<Queue>>, queue: &Arc<Mutex<Queue>>,
image_array: &Arc<Image>, image_array: &Arc<Image>,