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

Limits 1D texture mips to 1 #2374

Merged
merged 1 commit into from
Jan 10, 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
8 changes: 6 additions & 2 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 5 additions & 3 deletions wgpu-core/src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
139 changes: 110 additions & 29 deletions wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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)]
Expand Down
2 changes: 1 addition & 1 deletion wgpu/examples/skybox/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down