Skip to content

Commit

Permalink
Fix texture view creation with full-resource views when using an expl…
Browse files Browse the repository at this point in the history
…icit `mip_level_count` or `array_layer_count`
  • Loading branch information
cwfitzgerald committed Dec 21, 2022
1 parent e102cf9 commit 801b8cb
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non
- Evaluate `gfx_select!`'s `#[cfg]` conditions at the right time. By @jimblandy in [#3253](https://github.com/gfx-rs/wgpu/pull/3253)
- Improve error messages when binding bind group with dynamic offsets. By @cwfitzgerald in [#3294](https://github.com/gfx-rs/wgpu/pull/3294)

#### Metal
- Fix texture view creation with full-resource views when using an explicit `mip_level_count` or `array_layer_count`. By @cwfitzgerald in []()

#### WebGPU

- Use `log` instead of `println` in hello example by @JolifantoBambla in [#2858](https://github.com/gfx-rs/wgpu/pull/2858)
Expand Down
13 changes: 7 additions & 6 deletions wgpu-hal/src/metal/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,13 @@ impl crate::Device<super::Api> for super::Device {
conv::map_texture_view_dimension(desc.dimension)
};

//Note: this doesn't check properly if the mipmap level count or array layer count
// is explicitly set to 1.
let raw = if raw_format == texture.raw_format
&& raw_type == texture.raw_type
&& desc.range == wgt::ImageSubresourceRange::default()
{
let format_equal = raw_format == texture.raw_format;
let type_equal = raw_type == texture.raw_type;
let range_full_resource = desc
.range
.is_full_resource(texture.mip_levels, texture.array_layers);

let raw = if format_equal && type_equal && range_full_resource {
// Some images are marked as framebuffer-only, and we can't create aliases of them.
// Also helps working around Metal bugs with aliased array textures.
texture.raw.to_owned()
Expand Down
55 changes: 55 additions & 0 deletions wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5019,6 +5019,61 @@ pub struct ImageSubresourceRange {
}

impl ImageSubresourceRange {
/// Returns if the given range represents a full resource, with a texture of the given
/// layer count and mip count.
///
/// ```rust
/// # use wgpu_types as wgpu;
/// use std::num::NonZeroU32;
///
/// let range_none = wgpu::ImageSubresourceRange {
/// aspect: wgpu::TextureAspect::All,
/// base_mip_level: 0,
/// mip_level_count: None,
/// base_array_layer: 0,
/// array_layer_count: None,
/// };
/// assert_eq!(range_none.is_full_resource(5, 10), true);
///
/// let range_some = wgpu::ImageSubresourceRange {
/// aspect: wgpu::TextureAspect::All,
/// base_mip_level: 0,
/// mip_level_count: NonZeroU32::new(5),
/// base_array_layer: 0,
/// array_layer_count: NonZeroU32::new(10),
/// };
/// assert_eq!(range_some.is_full_resource(5, 10), true);
///
/// let range_mixed = wgpu::ImageSubresourceRange {
/// aspect: wgpu::TextureAspect::All,
/// base_mip_level: 0,
/// // Only partial resource
/// mip_level_count: NonZeroU32::new(3),
/// base_array_layer: 0,
/// array_layer_count: None,
/// };
/// assert_eq!(range_mixed.is_full_resource(5, 10), false);
/// ```
pub fn is_full_resource(&self, mip_levels: u32, array_layers: u32) -> bool {
// Mip level count and array layer count need to deal with both the None and Some(count) case.
let mip_level_count = self.mip_level_count.map_or(mip_levels, NonZeroU32::get);
let array_layer_count = self.array_layer_count.map_or(array_layers, NonZeroU32::get);

let aspect_eq = self.aspect == TextureAspect::All;

let base_mip_level_eq = self.base_mip_level == 0;
let mip_level_count_eq = mip_level_count == mip_levels;

let base_array_layer_eq = self.base_array_layer == 0;
let array_layer_count_eq = array_layer_count == array_layers;

aspect_eq
&& base_mip_level_eq
&& mip_level_count_eq
&& base_array_layer_eq
&& array_layer_count_eq
}

/// Returns the mip level range of a subresource range describes for a specific texture.
pub fn mip_range<L>(&self, texture_desc: &TextureDescriptor<L>) -> Range<u32> {
self.base_mip_level..match self.mip_level_count {
Expand Down

0 comments on commit 801b8cb

Please sign in to comment.