Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better error message when source is too small for ImmutableImage #2022

Merged
merged 2 commits into from
Oct 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions vulkano/src/image/immutable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
buffer::{BufferAccess, BufferContents, BufferUsage, CpuAccessibleBuffer},
command_buffer::{
allocator::CommandBufferAllocator, AutoCommandBufferBuilder, BlitImageInfo,
CommandBufferBeginError, CommandBufferExecFuture, CommandBufferUsage,
BufferImageCopy, CommandBufferBeginError, CommandBufferExecFuture, CommandBufferUsage,
CopyBufferToImageInfo, ImageBlit, PrimaryCommandBuffer,
},
device::{Device, DeviceOwned, Queue},
Expand All @@ -31,9 +31,9 @@ use crate::{
},
sampler::Filter,
sync::{NowFuture, Sharing},
OomError,
DeviceSize, OomError,
};
use smallvec::SmallVec;
use smallvec::{smallvec, SmallVec};
use std::{
error::Error,
fmt::{Display, Error as FmtError, Formatter},
Expand Down Expand Up @@ -218,6 +218,23 @@ impl ImmutableImage {
command_buffer_allocator: &impl CommandBufferAllocator,
queue: Arc<Queue>,
) -> Result<(Arc<Self>, CommandBufferExecFuture<NowFuture>), ImmutableImageCreationError> {
let region = BufferImageCopy {
image_subresource: ImageSubresourceLayers::from_parameters(
format,
dimensions.array_layers(),
),
image_extent: dimensions.width_height_depth(),
..Default::default()
};
let required_size = region.buffer_copy_size(format);

if source.size() < required_size {
return Err(ImmutableImageCreationError::SourceTooSmall {
source_size: source.size(),
required_size,
});
}

let need_to_generate_mipmaps = has_mipmaps(mip_levels);
let usage = ImageUsage {
transfer_dst: true,
Expand Down Expand Up @@ -248,8 +265,11 @@ impl ImmutableImage {
queue.queue_family_index(),
CommandBufferUsage::MultipleSubmit,
)?;
cbb.copy_buffer_to_image(CopyBufferToImageInfo::buffer_image(source, initializer))
.unwrap();
cbb.copy_buffer_to_image(CopyBufferToImageInfo {
regions: smallvec![region],
..CopyBufferToImageInfo::buffer_image(source, initializer)
})
.unwrap();

if need_to_generate_mipmaps {
generate_mipmaps(
Expand Down Expand Up @@ -394,11 +414,19 @@ where
}
}

/// Error that can happen when creating an `ImmutableImage`.
#[derive(Clone, Debug)]
pub enum ImmutableImageCreationError {
ImageCreationError(ImageCreationError),
DeviceMemoryAllocationError(DeviceMemoryError),
CommandBufferBeginError(CommandBufferBeginError),

/// The size of the provided source data is less than the required size for an image with the
/// given format and dimensions.
SourceTooSmall {
source_size: DeviceSize,
required_size: DeviceSize,
},
}

impl Error for ImmutableImageCreationError {
Expand All @@ -407,6 +435,7 @@ impl Error for ImmutableImageCreationError {
Self::ImageCreationError(err) => Some(err),
Self::DeviceMemoryAllocationError(err) => Some(err),
Self::CommandBufferBeginError(err) => Some(err),
_ => None,
}
}
}
Expand All @@ -417,6 +446,15 @@ impl Display for ImmutableImageCreationError {
Self::ImageCreationError(err) => err.fmt(f),
Self::DeviceMemoryAllocationError(err) => err.fmt(f),
Self::CommandBufferBeginError(err) => err.fmt(f),

Self::SourceTooSmall {
source_size,
required_size,
} => write!(
f,
"the size of the provided source data ({} bytes) is less than the required size for an image of the given format and dimensions ({} bytes)",
source_size, required_size,
),
}
}
}
Expand Down
43 changes: 43 additions & 0 deletions vulkano/src/image/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,31 @@ pub struct ImageSubresourceLayers {
pub array_layers: Range<u32>,
}

impl ImageSubresourceLayers {
/// Returns an `ImageSubresourceLayers` from the given image parameters, covering the first
/// mip level of the image. All aspects of the image are selected, or `plane0` if the image
/// is multi-planar.
#[inline]
pub fn from_parameters(format: Format, array_layers: u32) -> Self {
Self {
aspects: {
let aspects = format.aspects();

if aspects.plane0 {
ImageAspects {
plane0: true,
..ImageAspects::empty()
}
} else {
aspects
}
},
mip_level: 0,
array_layers: 0..array_layers,
}
}
}

impl From<ImageSubresourceLayers> for ash::vk::ImageSubresourceLayers {
#[inline]
fn from(val: ImageSubresourceLayers) -> Self {
Expand Down Expand Up @@ -550,6 +575,24 @@ pub struct ImageSubresourceRange {
pub array_layers: Range<u32>,
}

impl ImageSubresourceRange {
/// Returns an `ImageSubresourceRange` from the given image parameters, covering the whole
/// image. If the image is multi-planar, only the `color` aspect is selected.
#[inline]
pub fn from_parameters(format: Format, mip_levels: u32, array_layers: u32) -> Self {
Self {
aspects: ImageAspects {
plane0: false,
plane1: false,
plane2: false,
..format.aspects()
},
mip_levels: 0..mip_levels,
array_layers: 0..array_layers,
}
}
}

impl From<ImageSubresourceRange> for ash::vk::ImageSubresourceRange {
#[inline]
fn from(val: ImageSubresourceRange) -> Self {
Expand Down
17 changes: 1 addition & 16 deletions vulkano/src/image/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,7 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
/// of the image are selected, or `plane0` if the image is multi-planar.
#[inline]
fn subresource_layers(&self) -> ImageSubresourceLayers {
ImageSubresourceLayers {
aspects: {
let aspects = self.format().aspects();

if aspects.plane0 {
ImageAspects {
plane0: true,
..ImageAspects::empty()
}
} else {
aspects
}
},
mip_level: 0,
array_layers: 0..self.dimensions().array_layers(),
}
ImageSubresourceLayers::from_parameters(self.format(), self.dimensions().array_layers())
}

/// Returns an `ImageSubresourceRange` covering the whole image. If the image is multi-planar,
Expand Down