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

Fix texture view creation with full-resource views when using an explicit mip_level_count or array_layer_count #3323

Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ jobs:
run: |
set -e

cargo test --doc
cargo test --doc -p wgpu -p wgpu-core -p wgpu-hal -p wgpu-types

fmt:
name: Format
Expand Down
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 [#3323](https://github.com/gfx-rs/wgpu/pull/3323)

#### WebGPU

- Use `log` instead of `println` in hello example by @JolifantoBambla in [#2858](https://github.com/gfx-rs/wgpu/pull/2858)
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ members = [
"run-wasm"
]
exclude = []
default-members = ["wgpu", "wgpu-hal", "wgpu-info"]
default-members = ["wgpu", "wgpu-hal", "wgpu-info", "wgpu-types"]

[workspace.package]
edition = "2021"
Expand Down
2 changes: 1 addition & 1 deletion wgpu-core/src/track/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ This allows us to compose the operations to form the various kinds of tracker me
that need to happen in the codebase. For each resource in the given merger, the following
operation applies:

```
```text
UsageScope <- Resource = insert(scope, usage) OR merge(scope, usage)
UsageScope <- UsageScope = insert(scope, scope) OR merge(scope, scope)
CommandBuffer <- UsageScope = insert(buffer.start, buffer.end, scope)
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
1 change: 1 addition & 0 deletions wgpu-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ bitflags = "1"
serde = { version = "1", features = ["serde_derive"], optional = true }

[dev-dependencies]
serde = { version = "1", features = ["serde_derive"] }
serde_json = "1.0.85"
61 changes: 58 additions & 3 deletions wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
)]
#![warn(missing_docs, unsafe_op_in_unsafe_fn)]

#[cfg(feature = "serde")]
#[cfg(any(feature = "serde", test))]
use serde::{Deserialize, Serialize};
use std::hash::{Hash, Hasher};
use std::{num::NonZeroU32, ops::Range};
Expand Down Expand Up @@ -2103,7 +2103,7 @@ pub enum TextureFormat {
},
}

#[cfg(feature = "serde")]
#[cfg(any(feature = "serde", test))]
impl<'de> Deserialize<'de> for TextureFormat {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down Expand Up @@ -2239,7 +2239,7 @@ impl<'de> Deserialize<'de> for TextureFormat {
}
}

#[cfg(feature = "serde")]
#[cfg(any(feature = "serde", test))]
impl Serialize for TextureFormat {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down 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