Change type of mip_level_count and array_layer_count (members of TextureViewDescriptor and ImageSubresourceRange) from Option<NonZeroU32> to Option<u32> (#3445)

Clean up duplicated code related to texture layers/mips.
This commit is contained in:
Teodor Tanasoaia 2023-02-03 15:03:34 +01:00 committed by GitHub
parent 6399dd4866
commit 41de797c74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 168 additions and 269 deletions

View File

@ -40,6 +40,12 @@ Bottom level categories:
## Unreleased ## Unreleased
### Major changes
#### General
- Change type of `mip_level_count` and `array_layer_count` (members of `TextureViewDescriptor` and `ImageSubresourceRange`) from `Option<NonZeroU32>` to `Option<u32>`. By @teoxoy in [#3445](https://github.com/gfx-rs/wgpu/pull/3445)
### Changes ### Changes
#### WebGPU #### WebGPU

View File

@ -73,11 +73,8 @@ pub struct CreateTextureViewArgs {
label: Option<String>, label: Option<String>,
format: Option<wgpu_types::TextureFormat>, format: Option<wgpu_types::TextureFormat>,
dimension: Option<wgpu_types::TextureViewDimension>, dimension: Option<wgpu_types::TextureViewDimension>,
aspect: wgpu_types::TextureAspect, #[serde(flatten)]
base_mip_level: u32, range: wgpu_types::ImageSubresourceRange,
mip_level_count: Option<u32>,
base_array_layer: u32,
array_layer_count: Option<u32>,
} }
#[op] #[op]
@ -95,13 +92,7 @@ pub fn op_webgpu_create_texture_view(
label: args.label.map(Cow::from), label: args.label.map(Cow::from),
format: args.format, format: args.format,
dimension: args.dimension, dimension: args.dimension,
range: wgpu_types::ImageSubresourceRange { range: args.range,
aspect: args.aspect,
base_mip_level: args.base_mip_level,
mip_level_count: std::num::NonZeroU32::new(args.mip_level_count.unwrap_or(0)),
base_array_layer: args.base_array_layer,
array_layer_count: std::num::NonZeroU32::new(args.array_layer_count.unwrap_or(0)),
},
}; };
gfx_put!(texture => instance.texture_create_view( gfx_put!(texture => instance.texture_create_view(

View File

@ -53,14 +53,14 @@ whereas subesource range specified start {subresource_base_mip_level} and count
InvalidTextureLevelRange { InvalidTextureLevelRange {
texture_level_range: Range<u32>, texture_level_range: Range<u32>,
subresource_base_mip_level: u32, subresource_base_mip_level: u32,
subresource_mip_level_count: Option<NonZeroU32>, subresource_mip_level_count: Option<u32>,
}, },
#[error("image subresource layer range is outside of the texture's layer range. texture range is {texture_layer_range:?}, \ #[error("image subresource layer range is outside of the texture's layer range. texture range is {texture_layer_range:?}, \
whereas subesource range specified start {subresource_base_array_layer} and count {subresource_array_layer_count:?}")] whereas subesource range specified start {subresource_base_array_layer} and count {subresource_array_layer_count:?}")]
InvalidTextureLayerRange { InvalidTextureLayerRange {
texture_layer_range: Range<u32>, texture_layer_range: Range<u32>,
subresource_base_array_layer: u32, subresource_base_array_layer: u32,
subresource_array_layer_count: Option<NonZeroU32>, subresource_array_layer_count: Option<u32>,
}, },
} }
@ -188,12 +188,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}; };
// Check if subresource level range is valid // Check if subresource level range is valid
let subresource_level_end = match subresource_range.mip_level_count { let subresource_mip_range = subresource_range.mip_range(dst_texture.full_range.mips.end);
Some(count) => subresource_range.base_mip_level + count.get(), if dst_texture.full_range.mips.start > subresource_mip_range.start
None => dst_texture.full_range.mips.end, || dst_texture.full_range.mips.end < subresource_mip_range.end
};
if dst_texture.full_range.mips.start > subresource_range.base_mip_level
|| dst_texture.full_range.mips.end < subresource_level_end
{ {
return Err(ClearError::InvalidTextureLevelRange { return Err(ClearError::InvalidTextureLevelRange {
texture_level_range: dst_texture.full_range.mips.clone(), texture_level_range: dst_texture.full_range.mips.clone(),
@ -202,12 +199,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}); });
} }
// Check if subresource layer range is valid // Check if subresource layer range is valid
let subresource_layer_end = match subresource_range.array_layer_count { let subresource_layer_range =
Some(count) => subresource_range.base_array_layer + count.get(), subresource_range.layer_range(dst_texture.full_range.layers.end);
None => dst_texture.full_range.layers.end, if dst_texture.full_range.layers.start > subresource_layer_range.start
}; || dst_texture.full_range.layers.end < subresource_layer_range.end
if dst_texture.full_range.layers.start > subresource_range.base_array_layer
|| dst_texture.full_range.layers.end < subresource_layer_end
{ {
return Err(ClearError::InvalidTextureLayerRange { return Err(ClearError::InvalidTextureLayerRange {
texture_layer_range: dst_texture.full_range.layers.clone(), texture_layer_range: dst_texture.full_range.layers.clone(),
@ -222,8 +217,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&*texture_guard, &*texture_guard,
Valid(dst), Valid(dst),
TextureInitRange { TextureInitRange {
mip_range: subresource_range.base_mip_level..subresource_level_end, mip_range: subresource_mip_range,
layer_range: subresource_range.base_array_layer..subresource_layer_end, layer_range: subresource_layer_range,
}, },
cmd_buf.encoder.open(), cmd_buf.encoder.open(),
&mut cmd_buf.trackers.textures, &mut cmd_buf.trackers.textures,

View File

@ -191,7 +191,8 @@ pub(crate) fn extract_texture_selector<A: hal::Api>(
} }
let (layers, origin_z) = match texture.desc.dimension { let (layers, origin_z) = match texture.desc.dimension {
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => ( wgt::TextureDimension::D1 => (0..1, 0),
wgt::TextureDimension::D2 => (
copy_texture.origin.z..copy_texture.origin.z + copy_size.depth_or_array_layers, copy_texture.origin.z..copy_texture.origin.z + copy_size.depth_or_array_layers,
0, 0,
), ),
@ -323,7 +324,7 @@ pub(crate) fn validate_linear_texture_data(
/// ///
/// Returns the HAL copy extent and the layer count. /// Returns the HAL copy extent and the layer count.
/// ///
/// [vtcr]: https://gpuweb.github.io/gpuweb/#valid-texture-copy-range /// [vtcr]: https://gpuweb.github.io/gpuweb/#validating-texture-copy-range
pub(crate) fn validate_texture_copy_range( pub(crate) fn validate_texture_copy_range(
texture_copy_view: &ImageCopyTexture, texture_copy_view: &ImageCopyTexture,
desc: &wgt::TextureDescriptor<(), Vec<wgt::TextureFormat>>, desc: &wgt::TextureDescriptor<(), Vec<wgt::TextureFormat>>,
@ -417,9 +418,8 @@ pub(crate) fn validate_texture_copy_range(
} }
let (depth, array_layer_count) = match desc.dimension { let (depth, array_layer_count) = match desc.dimension {
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => { wgt::TextureDimension::D1 => (1, 1),
(1, copy_size.depth_or_array_layers) wgt::TextureDimension::D2 => (1, copy_size.depth_or_array_layers),
}
wgt::TextureDimension::D3 => (copy_size.depth_or_array_layers, 1), wgt::TextureDimension::D3 => (copy_size.depth_or_array_layers, 1),
}; };

View File

@ -931,9 +931,9 @@ impl<A: HalApi> Device<A> {
range: wgt::ImageSubresourceRange { range: wgt::ImageSubresourceRange {
aspect: wgt::TextureAspect::All, aspect: wgt::TextureAspect::All,
base_mip_level: mip_level, base_mip_level: mip_level,
mip_level_count: NonZeroU32::new(1), mip_level_count: Some(1),
base_array_layer: array_layer, base_array_layer: array_layer,
array_layer_count: NonZeroU32::new(1), array_layer_count: Some(1),
}, },
}; };
clear_views.push( clear_views.push(
@ -992,33 +992,28 @@ impl<A: HalApi> Device<A> {
wgt::TextureDimension::D3 => wgt::TextureViewDimension::D3, wgt::TextureDimension::D3 => wgt::TextureViewDimension::D3,
}); });
let resolved_mip_level_count = desc let resolved_mip_level_count = desc.range.mip_level_count.unwrap_or_else(|| {
.range texture
.mip_level_count .desc
.map(NonZeroU32::get) .mip_level_count
.unwrap_or_else(|| { .saturating_sub(desc.range.base_mip_level)
texture });
.desc
.mip_level_count
.saturating_sub(desc.range.base_mip_level)
});
let resolved_array_layer_count = desc let resolved_array_layer_count =
.range desc.range
.array_layer_count .array_layer_count
.map(NonZeroU32::get) .unwrap_or_else(|| match resolved_dimension {
.unwrap_or_else(|| match resolved_dimension { wgt::TextureViewDimension::D1
wgt::TextureViewDimension::D1 | wgt::TextureViewDimension::D2
| wgt::TextureViewDimension::D2 | wgt::TextureViewDimension::D3 => 1,
| wgt::TextureViewDimension::D3 => 1, wgt::TextureViewDimension::Cube => 6,
wgt::TextureViewDimension::Cube => 6, wgt::TextureViewDimension::D2Array | wgt::TextureViewDimension::CubeArray => {
wgt::TextureViewDimension::D2Array | wgt::TextureViewDimension::CubeArray => { texture
texture .desc
.desc .array_layer_count()
.array_layer_count() .saturating_sub(desc.range.base_array_layer)
.saturating_sub(desc.range.base_array_layer) }
} });
});
// validate TextureViewDescriptor // validate TextureViewDescriptor
@ -1179,9 +1174,9 @@ impl<A: HalApi> Device<A> {
let resolved_range = wgt::ImageSubresourceRange { let resolved_range = wgt::ImageSubresourceRange {
aspect: desc.range.aspect, aspect: desc.range.aspect,
base_mip_level: desc.range.base_mip_level, base_mip_level: desc.range.base_mip_level,
mip_level_count: NonZeroU32::new(resolved_mip_level_count), mip_level_count: Some(resolved_mip_level_count),
base_array_layer: desc.range.base_array_layer, base_array_layer: desc.range.base_array_layer,
array_layer_count: NonZeroU32::new(resolved_array_layer_count), array_layer_count: Some(resolved_array_layer_count),
}; };
let hal_desc = hal::TextureViewDescriptor { let hal_desc = hal::TextureViewDescriptor {
@ -1878,8 +1873,11 @@ impl<A: HalApi> Device<A> {
used_texture_ranges.push(TextureInitTrackerAction { used_texture_ranges.push(TextureInitTrackerAction {
id: view.parent_id.value.0, id: view.parent_id.value.0,
range: TextureInitRange { range: TextureInitRange {
mip_range: view.desc.range.mip_range(&texture.desc), mip_range: view.desc.range.mip_range(texture.desc.mip_level_count),
layer_range: view.desc.range.layer_range(&texture.desc), layer_range: view
.desc
.range
.layer_range(texture.desc.array_layer_count()),
}, },
kind: MemoryInitKind::NeedsInitializedMemory, kind: MemoryInitKind::NeedsInitializedMemory,
}); });

View File

@ -105,7 +105,7 @@ use crate::{
pipeline, resource, pipeline, resource,
}; };
use std::{fmt, num::NonZeroU32, ops}; use std::{fmt, ops};
use thiserror::Error; use thiserror::Error;
pub(crate) use buffer::{BufferBindGroupState, BufferTracker, BufferUsageScope}; pub(crate) use buffer::{BufferBindGroupState, BufferTracker, BufferUsageScope};
@ -162,9 +162,9 @@ impl PendingTransition<hal::TextureUses> {
range: wgt::ImageSubresourceRange { range: wgt::ImageSubresourceRange {
aspect: wgt::TextureAspect::All, aspect: wgt::TextureAspect::All,
base_mip_level: self.selector.mips.start, base_mip_level: self.selector.mips.start,
mip_level_count: unsafe { Some(NonZeroU32::new_unchecked(mip_count)) }, mip_level_count: Some(mip_count),
base_array_layer: self.selector.layers.start, base_array_layer: self.selector.layers.start,
array_layer_count: unsafe { Some(NonZeroU32::new_unchecked(layer_count)) }, array_layer_count: Some(layer_count),
}, },
usage: self.usage, usage: self.usage,
} }

View File

@ -384,20 +384,12 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
} }
}; };
let mip_level_count = match barrier.range.mip_level_count { let tex_mip_level_count = barrier.texture.mip_level_count;
Some(count) => count.get(), let tex_array_layer_count = barrier.texture.array_layer_count();
None => barrier.texture.mip_level_count - barrier.range.base_mip_level,
};
let array_layer_count = match barrier.range.array_layer_count {
Some(count) => count.get(),
None => barrier.texture.array_layer_count() - barrier.range.base_array_layer,
};
if barrier.range.aspect == wgt::TextureAspect::All if barrier
&& barrier.range.base_mip_level == 0 .range
&& mip_level_count == barrier.texture.mip_level_count .is_full_resource(tex_mip_level_count, tex_array_layer_count)
&& barrier.range.base_array_layer == 0
&& array_layer_count == barrier.texture.array_layer_count()
{ {
// Only one barrier if it affects the whole image. // Only one barrier if it affects the whole image.
self.temp.barriers.push(raw); self.temp.barriers.push(raw);
@ -415,16 +407,13 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
0..1 0..1
}; };
for rel_mip_level in 0..mip_level_count { for mip_level in barrier.range.mip_range(tex_mip_level_count) {
for rel_array_layer in 0..array_layer_count { for array_layer in barrier.range.layer_range(tex_array_layer_count) {
for plane in planes.clone() { for plane in planes.clone() {
unsafe { unsafe {
raw.u.Transition_mut().Subresource = raw.u.Transition_mut().Subresource = barrier
barrier.texture.calc_subresource( .texture
barrier.range.base_mip_level + rel_mip_level, .calc_subresource(mip_level, array_layer, plane);
barrier.range.base_array_layer + rel_array_layer,
plane,
);
}; };
self.temp.barriers.push(raw); self.temp.barriers.push(raw);
} }

View File

@ -434,10 +434,8 @@ unsafe impl Sync for Texture {}
impl Texture { impl Texture {
fn array_layer_count(&self) -> u32 { fn array_layer_count(&self) -> u32 {
match self.dimension { match self.dimension {
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => { wgt::TextureDimension::D1 | wgt::TextureDimension::D3 => 1,
self.size.depth_or_array_layers wgt::TextureDimension::D2 => self.size.depth_or_array_layers,
}
wgt::TextureDimension::D3 => 1,
} }
} }

View File

@ -23,15 +23,9 @@ impl crate::TextureViewDescriptor<'_> {
format_nodepth: auxil::dxgi::conv::map_texture_format_nodepth(self.format), format_nodepth: auxil::dxgi::conv::map_texture_format_nodepth(self.format),
multisampled: texture.sample_count > 1, multisampled: texture.sample_count > 1,
mip_level_base: self.range.base_mip_level, mip_level_base: self.range.base_mip_level,
mip_level_count: match self.range.mip_level_count { mip_level_count: self.range.mip_level_count.unwrap_or(!0),
Some(count) => count.get(),
None => !0,
},
array_layer_base: self.range.base_array_layer, array_layer_base: self.range.base_array_layer,
array_layer_count: match self.range.array_layer_count { array_layer_count: self.range.array_layer_count.unwrap_or(!0),
Some(count) => count.get(),
None => !0,
},
} }
} }
} }

View File

@ -101,9 +101,7 @@ impl super::Device {
desc: &crate::TextureDescriptor, desc: &crate::TextureDescriptor,
drop_guard: Option<crate::DropGuard>, drop_guard: Option<crate::DropGuard>,
) -> super::Texture { ) -> super::Texture {
let mut copy_size = crate::CopyExtent::map_extent_to_copy_size(&desc.size, desc.dimension); let (target, _, is_cubemap) = super::Texture::get_info_from_desc(desc);
let (target, _, is_cubemap) = super::Texture::get_info_from_desc(&mut copy_size, desc);
super::Texture { super::Texture {
inner: super::TextureInner::Texture { inner: super::TextureInner::Texture {
@ -112,14 +110,10 @@ impl super::Device {
}, },
drop_guard, drop_guard,
mip_level_count: desc.mip_level_count, mip_level_count: desc.mip_level_count,
array_layer_count: if desc.dimension == wgt::TextureDimension::D2 { array_layer_count: desc.array_layer_count(),
desc.size.depth_or_array_layers
} else {
1
},
format: desc.format, format: desc.format,
format_desc: self.shared.describe_texture_format(desc.format), format_desc: self.shared.describe_texture_format(desc.format),
copy_size, copy_size: desc.copy_extent(),
is_cubemap, is_cubemap,
} }
} }
@ -138,22 +132,16 @@ impl super::Device {
desc: &crate::TextureDescriptor, desc: &crate::TextureDescriptor,
drop_guard: Option<crate::DropGuard>, drop_guard: Option<crate::DropGuard>,
) -> super::Texture { ) -> super::Texture {
let copy_size = crate::CopyExtent::map_extent_to_copy_size(&desc.size, desc.dimension);
super::Texture { super::Texture {
inner: super::TextureInner::Renderbuffer { inner: super::TextureInner::Renderbuffer {
raw: glow::NativeRenderbuffer(name), raw: glow::NativeRenderbuffer(name),
}, },
drop_guard, drop_guard,
mip_level_count: desc.mip_level_count, mip_level_count: desc.mip_level_count,
array_layer_count: if desc.dimension == wgt::TextureDimension::D2 { array_layer_count: desc.array_layer_count(),
desc.size.depth_or_array_layers
} else {
1
},
format: desc.format, format: desc.format,
format_desc: self.shared.describe_texture_format(desc.format), format_desc: self.shared.describe_texture_format(desc.format),
copy_size, copy_size: desc.copy_extent(),
is_cubemap: false, is_cubemap: false,
} }
} }
@ -675,12 +663,6 @@ impl crate::Device<super::Api> for super::Device {
| crate::TextureUses::DEPTH_STENCIL_READ; | crate::TextureUses::DEPTH_STENCIL_READ;
let format_desc = self.shared.describe_texture_format(desc.format); let format_desc = self.shared.describe_texture_format(desc.format);
let mut copy_size = crate::CopyExtent {
width: desc.size.width,
height: desc.size.height,
depth: 1,
};
let (inner, is_cubemap) = if render_usage.contains(desc.usage) let (inner, is_cubemap) = if render_usage.contains(desc.usage)
&& desc.dimension == wgt::TextureDimension::D2 && desc.dimension == wgt::TextureDimension::D2
&& desc.size.depth_or_array_layers == 1 && desc.size.depth_or_array_layers == 1
@ -720,8 +702,7 @@ impl crate::Device<super::Api> for super::Device {
(super::TextureInner::Renderbuffer { raw }, false) (super::TextureInner::Renderbuffer { raw }, false)
} else { } else {
let raw = unsafe { gl.create_texture().unwrap() }; let raw = unsafe { gl.create_texture().unwrap() };
let (target, is_3d, is_cubemap) = let (target, is_3d, is_cubemap) = super::Texture::get_info_from_desc(desc);
super::Texture::get_info_from_desc(&mut copy_size, desc);
unsafe { gl.bind_texture(target, Some(raw)) }; unsafe { gl.bind_texture(target, Some(raw)) };
//Note: this has to be done before defining the storage! //Note: this has to be done before defining the storage!
@ -791,14 +772,10 @@ impl crate::Device<super::Api> for super::Device {
inner, inner,
drop_guard: None, drop_guard: None,
mip_level_count: desc.mip_level_count, mip_level_count: desc.mip_level_count,
array_layer_count: if desc.dimension == wgt::TextureDimension::D2 { array_layer_count: desc.array_layer_count(),
desc.size.depth_or_array_layers
} else {
1
},
format: desc.format, format: desc.format,
format_desc, format_desc,
copy_size, copy_size: desc.copy_extent(),
is_cubemap, is_cubemap,
}) })
} }
@ -828,22 +805,14 @@ impl crate::Device<super::Api> for super::Device {
texture: &super::Texture, texture: &super::Texture,
desc: &crate::TextureViewDescriptor, desc: &crate::TextureViewDescriptor,
) -> Result<super::TextureView, crate::DeviceError> { ) -> Result<super::TextureView, crate::DeviceError> {
let end_array_layer = match desc.range.array_layer_count {
Some(count) => desc.range.base_array_layer + count.get(),
None => texture.array_layer_count,
};
let end_mip_level = match desc.range.mip_level_count {
Some(count) => desc.range.base_mip_level + count.get(),
None => texture.mip_level_count,
};
Ok(super::TextureView { Ok(super::TextureView {
//TODO: use `conv::map_view_dimension(desc.dimension)`? //TODO: use `conv::map_view_dimension(desc.dimension)`?
inner: texture.inner.clone(), inner: texture.inner.clone(),
sample_type: texture.format.describe().sample_type, sample_type: texture.format.describe().sample_type,
aspects: crate::FormatAspects::from(texture.format) aspects: crate::FormatAspects::from(texture.format)
& crate::FormatAspects::from(desc.range.aspect), & crate::FormatAspects::from(desc.range.aspect),
mip_levels: desc.range.base_mip_level..end_mip_level, mip_levels: desc.range.mip_range(texture.mip_level_count),
array_layers: desc.range.base_array_layer..end_array_layer, array_layers: desc.range.layer_range(texture.array_layer_count),
format: texture.format, format: texture.format,
}) })
} }

View File

@ -319,35 +319,19 @@ impl Texture {
} }
/// Returns the `target`, whether the image is 3d and whether the image is a cubemap. /// Returns the `target`, whether the image is 3d and whether the image is a cubemap.
fn get_info_from_desc( fn get_info_from_desc(desc: &TextureDescriptor) -> (u32, bool, bool) {
copy_size: &mut CopyExtent,
desc: &TextureDescriptor,
) -> (u32, bool, bool) {
match desc.dimension { match desc.dimension {
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => { wgt::TextureDimension::D1 => (glow::TEXTURE_2D, false, false),
if desc.size.depth_or_array_layers > 1 { wgt::TextureDimension::D2 => {
//HACK: detect a cube map // HACK: detect a cube map; forces cube compatible textures to be cube textures
let cube_count = if desc.size.width == desc.size.height match (desc.is_cube_compatible(), desc.size.depth_or_array_layers) {
&& desc.size.depth_or_array_layers % 6 == 0 (false, 1) => (glow::TEXTURE_2D, false, false),
&& desc.sample_count == 1 (false, _) => (glow::TEXTURE_2D_ARRAY, true, false),
{ (true, 6) => (glow::TEXTURE_CUBE_MAP, false, true),
Some(desc.size.depth_or_array_layers / 6) (true, _) => (glow::TEXTURE_CUBE_MAP_ARRAY, true, true),
} else {
None
};
match cube_count {
None => (glow::TEXTURE_2D_ARRAY, true, false),
Some(1) => (glow::TEXTURE_CUBE_MAP, false, true),
Some(_) => (glow::TEXTURE_CUBE_MAP_ARRAY, true, true),
}
} else {
(glow::TEXTURE_2D, false, false)
} }
} }
wgt::TextureDimension::D3 => { wgt::TextureDimension::D3 => (glow::TEXTURE_3D, true, false),
copy_size.depth = desc.size.depth_or_array_layers;
(glow::TEXTURE_3D, true, false)
}
} }
} }
} }

View File

@ -872,6 +872,26 @@ pub struct TextureDescriptor<'a> {
pub view_formats: Vec<wgt::TextureFormat>, pub view_formats: Vec<wgt::TextureFormat>,
} }
impl TextureDescriptor<'_> {
pub fn copy_extent(&self) -> CopyExtent {
CopyExtent::map_extent_to_copy_size(&self.size, self.dimension)
}
pub fn is_cube_compatible(&self) -> bool {
self.dimension == wgt::TextureDimension::D2
&& self.size.depth_or_array_layers % 6 == 0
&& self.sample_count == 1
&& self.size.width == self.size.height
}
pub fn array_layer_count(&self) -> u32 {
match self.dimension {
wgt::TextureDimension::D1 | wgt::TextureDimension::D3 => 1,
wgt::TextureDimension::D2 => self.size.depth_or_array_layers,
}
}
}
/// TextureView descriptor. /// TextureView descriptor.
/// ///
/// Valid usage: /// Valid usage:

View File

@ -292,21 +292,9 @@ impl crate::Device<super::Api> for super::Device {
objc::rc::autoreleasepool(|| { objc::rc::autoreleasepool(|| {
let descriptor = mtl::TextureDescriptor::new(); let descriptor = mtl::TextureDescriptor::new();
let mut array_layers = desc.size.depth_or_array_layers;
let mut copy_size = crate::CopyExtent {
width: desc.size.width,
height: desc.size.height,
depth: 1,
};
let mtl_type = match desc.dimension { let mtl_type = match desc.dimension {
wgt::TextureDimension::D1 => { wgt::TextureDimension::D1 => mtl::MTLTextureType::D1,
if desc.size.depth_or_array_layers > 1 {
descriptor.set_array_length(desc.size.depth_or_array_layers as u64);
mtl::MTLTextureType::D1Array
} else {
mtl::MTLTextureType::D1
}
}
wgt::TextureDimension::D2 => { wgt::TextureDimension::D2 => {
if desc.sample_count > 1 { if desc.sample_count > 1 {
descriptor.set_sample_count(desc.sample_count as u64); descriptor.set_sample_count(desc.sample_count as u64);
@ -320,8 +308,6 @@ impl crate::Device<super::Api> for super::Device {
} }
wgt::TextureDimension::D3 => { wgt::TextureDimension::D3 => {
descriptor.set_depth(desc.size.depth_or_array_layers as u64); descriptor.set_depth(desc.size.depth_or_array_layers as u64);
array_layers = 1;
copy_size.depth = desc.size.depth_or_array_layers;
mtl::MTLTextureType::D3 mtl::MTLTextureType::D3
} }
}; };
@ -344,8 +330,8 @@ impl crate::Device<super::Api> for super::Device {
raw_format: mtl_format, raw_format: mtl_format,
raw_type: mtl_type, raw_type: mtl_type,
mip_levels: desc.mip_level_count, mip_levels: desc.mip_level_count,
array_layers, array_layers: desc.array_layer_count(),
copy_size, copy_size: desc.copy_extent(),
}) })
}) })
} }
@ -376,14 +362,14 @@ impl crate::Device<super::Api> for super::Device {
// Also helps working around Metal bugs with aliased array textures. // Also helps working around Metal bugs with aliased array textures.
texture.raw.to_owned() texture.raw.to_owned()
} else { } else {
let mip_level_count = match desc.range.mip_level_count { let mip_level_count = desc
Some(count) => count.get(), .range
None => texture.mip_levels - desc.range.base_mip_level, .mip_level_count
}; .unwrap_or(texture.mip_levels - desc.range.base_mip_level);
let array_layer_count = match desc.range.array_layer_count { let array_layer_count = desc
Some(count) => count.get(), .range
None => texture.array_layers - desc.range.base_array_layer, .array_layer_count
}; .unwrap_or(texture.array_layers - desc.range.base_array_layer);
objc::rc::autoreleasepool(|| { objc::rc::autoreleasepool(|| {
let raw = texture.raw.new_texture_view_from_slice( let raw = texture.raw.new_texture_view_from_slice(

View File

@ -1,5 +1,4 @@
use ash::vk; use ash::vk;
use std::num::NonZeroU32;
impl super::PrivateCapabilities { impl super::PrivateCapabilities {
pub fn map_texture_format(&self, format: wgt::TextureFormat) -> vk::Format { pub fn map_texture_format(&self, format: wgt::TextureFormat) -> vk::Format {
@ -585,20 +584,6 @@ pub fn map_copy_extent(extent: &crate::CopyExtent) -> vk::Extent3D {
} }
} }
pub fn map_extent_to_copy_size(
extent: &wgt::Extent3d,
dim: wgt::TextureDimension,
) -> crate::CopyExtent {
crate::CopyExtent {
width: extent.width,
height: extent.height,
depth: match dim {
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => 1,
wgt::TextureDimension::D3 => extent.depth_or_array_layers,
},
}
}
pub fn map_subresource_range( pub fn map_subresource_range(
range: &wgt::ImageSubresourceRange, range: &wgt::ImageSubresourceRange,
texture_aspect: crate::FormatAspects, texture_aspect: crate::FormatAspects,
@ -606,13 +591,11 @@ pub fn map_subresource_range(
vk::ImageSubresourceRange { vk::ImageSubresourceRange {
aspect_mask: map_aspects(crate::FormatAspects::from(range.aspect) & texture_aspect), aspect_mask: map_aspects(crate::FormatAspects::from(range.aspect) & texture_aspect),
base_mip_level: range.base_mip_level, base_mip_level: range.base_mip_level,
level_count: range level_count: range.mip_level_count.unwrap_or(vk::REMAINING_MIP_LEVELS),
.mip_level_count
.map_or(vk::REMAINING_MIP_LEVELS, NonZeroU32::get),
base_array_layer: range.base_array_layer, base_array_layer: range.base_array_layer,
layer_count: range layer_count: range
.array_layer_count .array_layer_count
.map_or(vk::REMAINING_ARRAY_LAYERS, NonZeroU32::get), .unwrap_or(vk::REMAINING_ARRAY_LAYERS),
} }
} }

View File

@ -643,7 +643,7 @@ impl super::Device {
aspects: crate::FormatAspects::from(desc.format), aspects: crate::FormatAspects::from(desc.format),
format_info: desc.format.describe(), format_info: desc.format.describe(),
raw_flags: vk::ImageCreateFlags::empty(), raw_flags: vk::ImageCreateFlags::empty(),
copy_size: crate::CopyExtent::map_extent_to_copy_size(&desc.size, desc.dimension), copy_size: desc.copy_extent(),
} }
} }
@ -900,18 +900,10 @@ impl crate::Device<super::Api> for super::Device {
&self, &self,
desc: &crate::TextureDescriptor, desc: &crate::TextureDescriptor,
) -> Result<super::Texture, crate::DeviceError> { ) -> Result<super::Texture, crate::DeviceError> {
let array_layer_count = match desc.dimension { let copy_size = desc.copy_extent();
wgt::TextureDimension::D3 => 1,
_ => desc.size.depth_or_array_layers,
};
let copy_size = conv::map_extent_to_copy_size(&desc.size, desc.dimension);
let mut raw_flags = vk::ImageCreateFlags::empty(); let mut raw_flags = vk::ImageCreateFlags::empty();
if desc.dimension == wgt::TextureDimension::D2 if desc.is_cube_compatible() {
&& desc.size.depth_or_array_layers % 6 == 0
&& desc.sample_count == 1
&& desc.size.width == desc.size.height
{
raw_flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE; raw_flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE;
} }
@ -937,13 +929,9 @@ impl crate::Device<super::Api> for super::Device {
.flags(raw_flags) .flags(raw_flags)
.image_type(conv::map_texture_dimension(desc.dimension)) .image_type(conv::map_texture_dimension(desc.dimension))
.format(original_format) .format(original_format)
.extent(vk::Extent3D { .extent(conv::map_copy_extent(&copy_size))
width: copy_size.width,
height: copy_size.height,
depth: copy_size.depth,
})
.mip_levels(desc.mip_level_count) .mip_levels(desc.mip_level_count)
.array_layers(array_layer_count) .array_layers(desc.array_layer_count())
.samples(vk::SampleCountFlags::from_raw(desc.sample_count)) .samples(vk::SampleCountFlags::from_raw(desc.sample_count))
.tiling(vk::ImageTiling::OPTIMAL) .tiling(vk::ImageTiling::OPTIMAL)
.usage(conv::map_texture_usage(desc.usage)) .usage(conv::map_texture_usage(desc.usage))

View File

@ -10,8 +10,6 @@ use ash::{
vk, vk,
}; };
use super::conv;
unsafe extern "system" fn debug_utils_messenger_callback( unsafe extern "system" fn debug_utils_messenger_callback(
message_severity: vk::DebugUtilsMessageSeverityFlagsEXT, message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
message_type: vk::DebugUtilsMessageTypeFlagsEXT, message_type: vk::DebugUtilsMessageTypeFlagsEXT,
@ -794,10 +792,11 @@ impl crate::Surface<super::Api> for super::Surface {
aspects: crate::FormatAspects::COLOR, aspects: crate::FormatAspects::COLOR,
format_info: sc.config.format.describe(), format_info: sc.config.format.describe(),
raw_flags: vk::ImageCreateFlags::empty(), raw_flags: vk::ImageCreateFlags::empty(),
copy_size: conv::map_extent_to_copy_size( copy_size: crate::CopyExtent {
&sc.config.extent, width: sc.config.extent.width,
wgt::TextureDimension::D2, height: sc.config.extent.height,
), depth: 1,
},
}, },
}; };
Ok(Some(crate::AcquiredSurfaceTexture { Ok(Some(crate::AcquiredSurfaceTexture {

View File

@ -749,8 +749,7 @@ pub struct Limits {
/// Defaults to 2048. Higher is "better". /// Defaults to 2048. Higher is "better".
#[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension3D"))] #[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension3D"))]
pub max_texture_dimension_3d: u32, pub max_texture_dimension_3d: u32,
/// Maximum allowed value for the `size.depth_or_array_layers` of a texture created with /// Maximum allowed value for the `size.depth_or_array_layers` of a texture created with `TextureDimension::D2`.
/// `TextureDimension::D1` or `TextureDimension::D2`.
/// Defaults to 256. Higher is "better". /// Defaults to 256. Higher is "better".
pub max_texture_array_layers: u32, pub max_texture_array_layers: u32,
/// Amount of bind groups that can be attached to a pipeline at the same time. Defaults to 4. Higher is "better". /// Amount of bind groups that can be attached to a pipeline at the same time. Defaults to 4. Higher is "better".
@ -4363,8 +4362,9 @@ impl Extent3d {
_ => u32::max(1, self.height >> level), _ => u32::max(1, self.height >> level),
}, },
depth_or_array_layers: match dim { depth_or_array_layers: match dim {
TextureDimension::D1 => 1,
TextureDimension::D2 => self.depth_or_array_layers,
TextureDimension::D3 => u32::max(1, self.depth_or_array_layers >> level), TextureDimension::D3 => u32::max(1, self.depth_or_array_layers >> level),
_ => self.depth_or_array_layers,
}, },
} }
} }
@ -4504,9 +4504,12 @@ pub struct TextureDescriptor<L, V> {
pub view_formats: V, pub view_formats: V,
} }
impl<L, V: Clone> TextureDescriptor<L, V> { impl<L, V> TextureDescriptor<L, V> {
/// Takes a closure and maps the label of the texture descriptor into another. /// Takes a closure and maps the label of the texture descriptor into another.
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> TextureDescriptor<K, V> { pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> TextureDescriptor<K, V>
where
V: Clone,
{
TextureDescriptor { TextureDescriptor {
label: fun(&self.label), label: fun(&self.label),
size: self.size, size: self.size,
@ -4524,7 +4527,10 @@ impl<L, V: Clone> TextureDescriptor<L, V> {
&self, &self,
l_fun: impl FnOnce(&L) -> K, l_fun: impl FnOnce(&L) -> K,
v_fun: impl FnOnce(V) -> M, v_fun: impl FnOnce(V) -> M,
) -> TextureDescriptor<K, M> { ) -> TextureDescriptor<K, M>
where
V: Clone,
{
TextureDescriptor { TextureDescriptor {
label: l_fun(&self.label), label: l_fun(&self.label),
size: self.size, size: self.size,
@ -5372,13 +5378,13 @@ pub struct ImageSubresourceRange {
/// Mip level count. /// Mip level count.
/// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count. /// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count.
/// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total. /// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total.
pub mip_level_count: Option<NonZeroU32>, pub mip_level_count: Option<u32>,
/// Base array layer. /// Base array layer.
pub base_array_layer: u32, pub base_array_layer: u32,
/// Layer count. /// Layer count.
/// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count. /// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count.
/// If `None`, considered to include the rest of the array layers, but at least 1 in total. /// If `None`, considered to include the rest of the array layers, but at least 1 in total.
pub array_layer_count: Option<NonZeroU32>, pub array_layer_count: Option<u32>,
} }
impl ImageSubresourceRange { impl ImageSubresourceRange {
@ -5387,7 +5393,6 @@ impl ImageSubresourceRange {
/// ///
/// ```rust /// ```rust
/// # use wgpu_types as wgpu; /// # use wgpu_types as wgpu;
/// use std::num::NonZeroU32;
/// ///
/// let range_none = wgpu::ImageSubresourceRange { /// let range_none = wgpu::ImageSubresourceRange {
/// aspect: wgpu::TextureAspect::All, /// aspect: wgpu::TextureAspect::All,
@ -5401,9 +5406,9 @@ impl ImageSubresourceRange {
/// let range_some = wgpu::ImageSubresourceRange { /// let range_some = wgpu::ImageSubresourceRange {
/// aspect: wgpu::TextureAspect::All, /// aspect: wgpu::TextureAspect::All,
/// base_mip_level: 0, /// base_mip_level: 0,
/// mip_level_count: NonZeroU32::new(5), /// mip_level_count: Some(5),
/// base_array_layer: 0, /// base_array_layer: 0,
/// array_layer_count: NonZeroU32::new(10), /// array_layer_count: Some(10),
/// }; /// };
/// assert_eq!(range_some.is_full_resource(5, 10), true); /// assert_eq!(range_some.is_full_resource(5, 10), true);
/// ///
@ -5411,7 +5416,7 @@ impl ImageSubresourceRange {
/// aspect: wgpu::TextureAspect::All, /// aspect: wgpu::TextureAspect::All,
/// base_mip_level: 0, /// base_mip_level: 0,
/// // Only partial resource /// // Only partial resource
/// mip_level_count: NonZeroU32::new(3), /// mip_level_count: Some(3),
/// base_array_layer: 0, /// base_array_layer: 0,
/// array_layer_count: None, /// array_layer_count: None,
/// }; /// };
@ -5419,8 +5424,8 @@ impl ImageSubresourceRange {
/// ``` /// ```
pub fn is_full_resource(&self, mip_levels: u32, array_layers: u32) -> bool { 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. // 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 mip_level_count = self.mip_level_count.unwrap_or(mip_levels);
let array_layer_count = self.array_layer_count.map_or(array_layers, NonZeroU32::get); let array_layer_count = self.array_layer_count.unwrap_or(array_layers);
let aspect_eq = self.aspect == TextureAspect::All; let aspect_eq = self.aspect == TextureAspect::All;
@ -5438,24 +5443,18 @@ impl ImageSubresourceRange {
} }
/// Returns the mip level range of a subresource range describes for a specific texture. /// Returns the mip level range of a subresource range describes for a specific texture.
pub fn mip_range<L, V>(&self, texture_desc: &TextureDescriptor<L, V>) -> Range<u32> { pub fn mip_range(&self, mip_level_count: u32) -> Range<u32> {
self.base_mip_level..match self.mip_level_count { self.base_mip_level..match self.mip_level_count {
Some(mip_level_count) => self.base_mip_level + mip_level_count.get(), Some(mip_level_count) => self.base_mip_level + mip_level_count,
None => texture_desc.mip_level_count, None => mip_level_count,
} }
} }
/// Returns the layer range of a subresource range describes for a specific texture. /// Returns the layer range of a subresource range describes for a specific texture.
pub fn layer_range<L, V>(&self, texture_desc: &TextureDescriptor<L, V>) -> Range<u32> { pub fn layer_range(&self, array_layer_count: u32) -> Range<u32> {
self.base_array_layer..match self.array_layer_count { self.base_array_layer..match self.array_layer_count {
Some(array_layer_count) => self.base_array_layer + array_layer_count.get(), Some(array_layer_count) => self.base_array_layer + array_layer_count,
None => { None => array_layer_count,
if texture_desc.dimension == TextureDimension::D3 {
self.base_array_layer + 1
} else {
texture_desc.size.depth_or_array_layers
}
}
} }
} }
} }

View File

@ -126,7 +126,7 @@ impl Example {
dimension: None, dimension: None,
aspect: wgpu::TextureAspect::All, aspect: wgpu::TextureAspect::All,
base_mip_level: mip, base_mip_level: mip,
mip_level_count: NonZeroU32::new(1), mip_level_count: Some(1),
base_array_layer: 0, base_array_layer: 0,
array_layer_count: None, array_layer_count: None,
}) })

View File

@ -1,4 +1,4 @@
use std::{borrow::Cow, f32::consts, iter, mem, num::NonZeroU32, ops::Range, rc::Rc}; use std::{borrow::Cow, f32::consts, iter, mem, ops::Range, rc::Rc};
#[path = "../framework.rs"] #[path = "../framework.rs"]
mod framework; mod framework;
@ -400,7 +400,7 @@ impl framework::Example for Example {
base_mip_level: 0, base_mip_level: 0,
mip_level_count: None, mip_level_count: None,
base_array_layer: i as u32, base_array_layer: i as u32,
array_layer_count: NonZeroU32::new(1), array_layer_count: Some(1),
})) }))
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View File

@ -1809,11 +1809,11 @@ impl crate::context::Context for Context {
mapped.aspect(map_texture_aspect(desc.aspect)); mapped.aspect(map_texture_aspect(desc.aspect));
mapped.base_array_layer(desc.base_array_layer); mapped.base_array_layer(desc.base_array_layer);
if let Some(count) = desc.array_layer_count { if let Some(count) = desc.array_layer_count {
mapped.array_layer_count(count.get()); mapped.array_layer_count(count);
} }
mapped.base_mip_level(desc.base_mip_level); mapped.base_mip_level(desc.base_mip_level);
if let Some(count) = desc.mip_level_count { if let Some(count) = desc.mip_level_count {
mapped.mip_level_count(count.get()); mapped.mip_level_count(count);
} }
if let Some(label) = desc.label { if let Some(label) = desc.label {
mapped.label(label); mapped.label(label);

View File

@ -948,13 +948,13 @@ pub struct TextureViewDescriptor<'a> {
/// Mip level count. /// Mip level count.
/// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count. /// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count.
/// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total. /// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total.
pub mip_level_count: Option<NonZeroU32>, pub mip_level_count: Option<u32>,
/// Base array layer. /// Base array layer.
pub base_array_layer: u32, pub base_array_layer: u32,
/// Layer count. /// Layer count.
/// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count. /// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count.
/// If `None`, considered to include the rest of the array layers, but at least 1 in total. /// If `None`, considered to include the rest of the array layers, but at least 1 in total.
pub array_layer_count: Option<NonZeroU32>, pub array_layer_count: Option<u32>,
} }
static_assertions::assert_impl_all!(TextureViewDescriptor: Send, Sync); static_assertions::assert_impl_all!(TextureViewDescriptor: Send, Sync);