Limits 1D texture mips to 1

This commit is contained in:
Dzmitry Malyshau 2022-01-10 12:10:31 -05:00
parent f8a63c4055
commit 01f62baad2
4 changed files with 122 additions and 35 deletions

View File

@ -671,8 +671,12 @@ impl<A: HalApi> Device<A> {
)?;
let mips = desc.mip_level_count;
if mips == 0 || mips > hal::MAX_MIP_LEVELS || mips > desc.size.max_mips() {
return Err(resource::CreateTextureError::InvalidMipLevelCount(mips));
let max_levels_allowed = desc.size.max_mips(desc.dimension).min(hal::MAX_MIP_LEVELS);
if mips == 0 || mips > max_levels_allowed {
return Err(resource::CreateTextureError::InvalidMipLevelCount {
requested: mips,
maximum: max_levels_allowed,
});
}
// Enforce having COPY_DST/DEPTH_STENCIL_WRIT/COLOR_TARGET otherwise we wouldn't be able to initialize the texture.

View File

@ -301,9 +301,11 @@ pub enum CreateTextureError {
InvalidDimension(#[from] TextureDimensionError),
#[error("Depth texture kind {0:?} of format {0:?} can't be created")]
InvalidDepthKind(wgt::TextureDimension, wgt::TextureFormat),
#[error("texture descriptor mip level count ({0}) is invalid")]
InvalidMipLevelCount(u32),
#[error("The texture usages {0:?} are not allowed on a texture of type {1:?}")]
#[error(
"Texture descriptor mip level count {requested} is invalid, maximum allowed is {maximum}"
)]
InvalidMipLevelCount { requested: u32, maximum: u32 },
#[error("Texture usages {0:?} are not allowed on a texture of type {1:?}")]
InvalidUsages(wgt::TextureUsages, wgt::TextureFormat),
#[error("Texture format {0:?} can't be used")]
MissingFeatures(wgt::TextureFormat, #[source] MissingFeatures),

View File

@ -2848,25 +2848,6 @@ impl Extent3d {
///
/// This is the texture extent that you must upload at when uploading to _mipmaps_ of compressed textures.
///
/// ```rust
/// # use wgpu_types as wgpu;
/// let format = wgpu::TextureFormat::Bc1RgbaUnormSrgb; // 4x4 blocks
/// assert_eq!(
/// wgpu::Extent3d { width: 7, height: 7, depth_or_array_layers: 1 }.physical_size(format),
/// wgpu::Extent3d { width: 8, height: 8, depth_or_array_layers: 1 }
/// );
/// // Doesn't change, already aligned
/// assert_eq!(
/// wgpu::Extent3d { width: 8, height: 8, depth_or_array_layers: 1 }.physical_size(format),
/// wgpu::Extent3d { width: 8, height: 8, depth_or_array_layers: 1 }
/// );
/// let format = wgpu::TextureFormat::Astc8x5RgbaUnorm; // 8x5 blocks
/// assert_eq!(
/// wgpu::Extent3d { width: 7, height: 7, depth_or_array_layers: 1 }.physical_size(format),
/// wgpu::Extent3d { width: 8, height: 10, depth_or_array_layers: 1 }
/// );
/// ```
///
/// [physical size]: https://gpuweb.github.io/gpuweb/#physical-size
pub fn physical_size(&self, format: TextureFormat) -> Self {
let (block_width, block_height) = format.describe().block_dimensions;
@ -2887,16 +2868,18 @@ impl Extent3d {
///
/// Treats the depth as part of the mipmaps. If calculating
/// for a 2DArray texture, which does not mipmap depth, set depth to 1.
///
/// ```rust
/// # use wgpu_types as wgpu;
/// assert_eq!(wgpu::Extent3d { width: 1, height: 1, depth_or_array_layers: 1 }.max_mips(), 1);
/// assert_eq!(wgpu::Extent3d { width: 60, height: 60, depth_or_array_layers: 1 }.max_mips(), 6);
/// assert_eq!(wgpu::Extent3d { width: 240, height: 1, depth_or_array_layers: 1 }.max_mips(), 8);
/// ```
pub fn max_mips(&self) -> u32 {
let max_dim = self.width.max(self.height.max(self.depth_or_array_layers));
32 - max_dim.leading_zeros()
pub fn max_mips(&self, dim: TextureDimension) -> u32 {
match dim {
TextureDimension::D1 => 1,
TextureDimension::D2 => {
let max_dim = self.width.max(self.height);
32 - max_dim.leading_zeros()
}
TextureDimension::D3 => {
let max_dim = self.width.max(self.height.max(self.depth_or_array_layers));
32 - max_dim.leading_zeros()
}
}
}
/// Calculates the extent at a given mip level.
@ -2913,6 +2896,104 @@ impl Extent3d {
}
}
#[test]
fn test_physical_size() {
let format = TextureFormat::Bc1RgbaUnormSrgb; // 4x4 blocks
assert_eq!(
Extent3d {
width: 7,
height: 7,
depth_or_array_layers: 1
}
.physical_size(format),
Extent3d {
width: 8,
height: 8,
depth_or_array_layers: 1
}
);
// Doesn't change, already aligned
assert_eq!(
Extent3d {
width: 8,
height: 8,
depth_or_array_layers: 1
}
.physical_size(format),
Extent3d {
width: 8,
height: 8,
depth_or_array_layers: 1
}
);
let format = TextureFormat::Astc8x5RgbaUnorm; // 8x5 blocks
assert_eq!(
Extent3d {
width: 7,
height: 7,
depth_or_array_layers: 1
}
.physical_size(format),
Extent3d {
width: 8,
height: 10,
depth_or_array_layers: 1
}
);
}
#[test]
fn test_max_mips() {
// 1D
assert_eq!(
Extent3d {
width: 240,
height: 1,
depth_or_array_layers: 1
}
.max_mips(TextureDimension::D1),
1
);
// 2D
assert_eq!(
Extent3d {
width: 1,
height: 1,
depth_or_array_layers: 1
}
.max_mips(TextureDimension::D2),
1
);
assert_eq!(
Extent3d {
width: 60,
height: 60,
depth_or_array_layers: 1
}
.max_mips(TextureDimension::D2),
6
);
assert_eq!(
Extent3d {
width: 240,
height: 1,
depth_or_array_layers: 1000
}
.max_mips(TextureDimension::D2),
8
);
// 3D
assert_eq!(
Extent3d {
width: 16,
height: 30,
depth_or_array_layers: 60
}
.max_mips(TextureDimension::D3),
6
);
}
/// Describes a [`Texture`].
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]

View File

@ -295,7 +295,7 @@ impl framework::Example for Skybox {
depth_or_array_layers: 1,
..size
};
let max_mips = layer_size.max_mips();
let max_mips = layer_size.max_mips(wgpu::TextureDimension::D2);
log::debug!(
"Copying {:?} skybox images of size {}, {}, 6 with {} mips to gpu",