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,
|
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>,
|
||||||
|
|
Loading…
Reference in a new issue