Fix ImageDimensions::mipmap_dimensions and max_mipmaps where the original size is not a power of two. (#1228)

* Fix ImageDimensions::mipmap_dimensions

* Fix tests for ImageDimensions::mipmap_dimensions

* Fix ImageDimensions::max_mipmaps

* Fix docs for ImageDimensions::max_mipmaps

* Optimize ImageDimensions::max_mipmaps
This commit is contained in:
Icy Defiance 2019-10-20 00:01:25 -04:00 committed by Austin Johnson
parent 8b7ff28022
commit 8175081322
2 changed files with 27 additions and 38 deletions

View File

@ -2,6 +2,7 @@
- Update MacOS dependencies metal to 0.17 and cocoa to 0.19 - Update MacOS dependencies metal to 0.17 and cocoa to 0.19
- Added dynamic stencil elements to `DynamicState` - Added dynamic stencil elements to `DynamicState`
- Fixed `ImageDimensions::mipmap_dimensions` and `max_mipmaps` in cases where the original size is not a power of two.
# Version 0.14.0 (2019-08-17) # Version 0.14.0 (2019-08-17)

View File

@ -415,17 +415,11 @@ impl ImageDimensions {
/// array_layers: 1, /// array_layers: 1,
/// }; /// };
/// ///
/// assert_eq!(dims.max_mipmaps(), 7); /// assert_eq!(dims.max_mipmaps(), 6);
/// ``` /// ```
/// ///
/// # Panic
///
/// May panic if the dimensions are 0.
///
pub fn max_mipmaps(&self) -> u32 { pub fn max_mipmaps(&self) -> u32 {
let max_dim = cmp::max(cmp::max(self.width(), self.height()), self.depth()); 32 - (self.width() | self.height() | self.depth()).leading_zeros()
let num_zeroes = 32 - (max_dim - 1).leading_zeros();
num_zeroes + 1
} }
/// Returns the dimensions of the `level`th mipmap level. If `level` is 0, then the dimensions /// Returns the dimensions of the `level`th mipmap level. If `level` is 0, then the dimensions
@ -447,19 +441,19 @@ impl ImageDimensions {
/// ///
/// assert_eq!(dims.mipmap_dimensions(0), Some(dims)); /// assert_eq!(dims.mipmap_dimensions(0), Some(dims));
/// assert_eq!(dims.mipmap_dimensions(1), Some(ImageDimensions::Dim2d { /// assert_eq!(dims.mipmap_dimensions(1), Some(ImageDimensions::Dim2d {
/// width: 512, /// width: 481,
/// height: 128, /// height: 128,
/// cubemap_compatible: false, /// cubemap_compatible: false,
/// array_layers: 1, /// array_layers: 1,
/// })); /// }));
/// assert_eq!(dims.mipmap_dimensions(6), Some(ImageDimensions::Dim2d { /// assert_eq!(dims.mipmap_dimensions(6), Some(ImageDimensions::Dim2d {
/// width: 16, /// width: 15,
/// height: 4, /// height: 4,
/// cubemap_compatible: false, /// cubemap_compatible: false,
/// array_layers: 1, /// array_layers: 1,
/// })); /// }));
/// assert_eq!(dims.mipmap_dimensions(9), Some(ImageDimensions::Dim2d { /// assert_eq!(dims.mipmap_dimensions(9), Some(ImageDimensions::Dim2d {
/// width: 2, /// width: 1,
/// height: 1, /// height: 1,
/// cubemap_compatible: false, /// cubemap_compatible: false,
/// array_layers: 1, /// array_layers: 1,
@ -489,7 +483,7 @@ impl ImageDimensions {
debug_assert_ne!(width, 0); debug_assert_ne!(width, 0);
ImageDimensions::Dim1d { ImageDimensions::Dim1d {
array_layers: array_layers, array_layers: array_layers,
width: (((width - 1) >> level) + 1).next_power_of_two(), width: cmp::max(1, width >> level),
} }
}, },
@ -502,8 +496,8 @@ impl ImageDimensions {
debug_assert_ne!(width, 0); debug_assert_ne!(width, 0);
debug_assert_ne!(height, 0); debug_assert_ne!(height, 0);
ImageDimensions::Dim2d { ImageDimensions::Dim2d {
width: (((width - 1) >> level) + 1).next_power_of_two(), width: cmp::max(1, width >> level),
height: (((height - 1) >> level) + 1).next_power_of_two(), height: cmp::max(1, height >> level),
array_layers: array_layers, array_layers: array_layers,
cubemap_compatible: cubemap_compatible, cubemap_compatible: cubemap_compatible,
} }
@ -517,9 +511,9 @@ impl ImageDimensions {
debug_assert_ne!(width, 0); debug_assert_ne!(width, 0);
debug_assert_ne!(height, 0); debug_assert_ne!(height, 0);
ImageDimensions::Dim3d { ImageDimensions::Dim3d {
width: (((width - 1) >> level) + 1).next_power_of_two(), width: cmp::max(1, width >> level),
height: (((height - 1) >> level) + 1).next_power_of_two(), height: cmp::max(1, height >> level),
depth: (((depth - 1) >> level) + 1).next_power_of_two(), depth: cmp::max(1, depth >> level),
} }
}, },
}) })
@ -546,7 +540,7 @@ mod tests {
cubemap_compatible: false, cubemap_compatible: false,
array_layers: 1, array_layers: 1,
}; };
assert_eq!(dims.max_mipmaps(), 3); assert_eq!(dims.max_mipmaps(), 2);
let dims = ImageDimensions::Dim2d { let dims = ImageDimensions::Dim2d {
width: 512, width: 512,
@ -568,67 +562,61 @@ mod tests {
assert_eq!(dims.mipmap_dimensions(0), Some(dims)); assert_eq!(dims.mipmap_dimensions(0), Some(dims));
assert_eq!(dims.mipmap_dimensions(1), assert_eq!(dims.mipmap_dimensions(1),
Some(ImageDimensions::Dim2d { Some(ImageDimensions::Dim2d {
width: 256, width: 141,
height: 128, height: 87,
cubemap_compatible: false, cubemap_compatible: false,
array_layers: 1, array_layers: 1,
})); }));
assert_eq!(dims.mipmap_dimensions(2), assert_eq!(dims.mipmap_dimensions(2),
Some(ImageDimensions::Dim2d { Some(ImageDimensions::Dim2d {
width: 128, width: 70,
height: 64, height: 43,
cubemap_compatible: false, cubemap_compatible: false,
array_layers: 1, array_layers: 1,
})); }));
assert_eq!(dims.mipmap_dimensions(3), assert_eq!(dims.mipmap_dimensions(3),
Some(ImageDimensions::Dim2d { Some(ImageDimensions::Dim2d {
width: 64, width: 35,
height: 32, height: 21,
cubemap_compatible: false, cubemap_compatible: false,
array_layers: 1, array_layers: 1,
})); }));
assert_eq!(dims.mipmap_dimensions(4), assert_eq!(dims.mipmap_dimensions(4),
Some(ImageDimensions::Dim2d { Some(ImageDimensions::Dim2d {
width: 32, width: 17,
height: 16, height: 10,
cubemap_compatible: false, cubemap_compatible: false,
array_layers: 1, array_layers: 1,
})); }));
assert_eq!(dims.mipmap_dimensions(5), assert_eq!(dims.mipmap_dimensions(5),
Some(ImageDimensions::Dim2d { Some(ImageDimensions::Dim2d {
width: 16, width: 8,
height: 8, height: 5,
cubemap_compatible: false, cubemap_compatible: false,
array_layers: 1, array_layers: 1,
})); }));
assert_eq!(dims.mipmap_dimensions(6), assert_eq!(dims.mipmap_dimensions(6),
Some(ImageDimensions::Dim2d {
width: 8,
height: 4,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(7),
Some(ImageDimensions::Dim2d { Some(ImageDimensions::Dim2d {
width: 4, width: 4,
height: 2, height: 2,
cubemap_compatible: false, cubemap_compatible: false,
array_layers: 1, array_layers: 1,
})); }));
assert_eq!(dims.mipmap_dimensions(8), assert_eq!(dims.mipmap_dimensions(7),
Some(ImageDimensions::Dim2d { Some(ImageDimensions::Dim2d {
width: 2, width: 2,
height: 1, height: 1,
cubemap_compatible: false, cubemap_compatible: false,
array_layers: 1, array_layers: 1,
})); }));
assert_eq!(dims.mipmap_dimensions(9), assert_eq!(dims.mipmap_dimensions(8),
Some(ImageDimensions::Dim2d { Some(ImageDimensions::Dim2d {
width: 1, width: 1,
height: 1, height: 1,
cubemap_compatible: false, cubemap_compatible: false,
array_layers: 1, array_layers: 1,
})); }));
assert_eq!(dims.mipmap_dimensions(10), None); assert_eq!(dims.mipmap_dimensions(9), None);
} }
} }