mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Fix clamping at minimal render extent (#8486)
This was a regression introduced by #8307. For mipmapped multi-planar textures, requires that the size is a multiple of a power of two determined by the mip level count, in lieu of properly aligning the size of each mip level to an even dimension. See #8491. (The failure referred to by "fails due to missing validation" was fixed before the regression, by #8402, but was not identified as fixed and added to the test list at that time.)
This commit is contained in:
parent
c0607b53f5
commit
a2db631672
@ -126,9 +126,7 @@ fails-if(dx12) webgpu:api,validation,image_copy,layout_related:offset_alignment:
|
||||
webgpu:api,validation,image_copy,texture_related:format:dimension="1d";*
|
||||
webgpu:api,validation,queue,submit:command_buffer,*
|
||||
webgpu:api,validation,render_pass,render_pass_descriptor:attachments,*
|
||||
webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,depthSlice,bound_check:*
|
||||
// Fails due to missing validation.
|
||||
// FAIL: webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,depthSlice,overlaps,diff_miplevel:*
|
||||
webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,depthSlice,*
|
||||
webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,*
|
||||
webgpu:api,validation,render_pass,resolve:resolve_attachment:*
|
||||
webgpu:api,validation,resource_usages,buffer,in_pass_encoder:*
|
||||
@ -141,6 +139,7 @@ webgpu:api,validation,resource_usages,texture,in_pass_encoder:unused_bindings_in
|
||||
webgpu:api,validation,resource_usages,texture,in_render_common:subresources,multiple_bind_groups:bg0Levels={"base":0,"count":1};*
|
||||
webgpu:api,validation,texture,rg11b10ufloat_renderable:*
|
||||
webgpu:api,operation,render_pipeline,overrides:*
|
||||
webgpu:api,operation,rendering,3d_texture_slices:*
|
||||
webgpu:api,operation,rendering,basic:clear:*
|
||||
webgpu:api,operation,rendering,basic:fullscreen_quad:*
|
||||
//FAIL: webgpu:api,operation,rendering,basic:large_draw:*
|
||||
|
||||
@ -1360,8 +1360,25 @@ impl Device {
|
||||
}
|
||||
}
|
||||
|
||||
let mips = desc.mip_level_count;
|
||||
let max_levels_allowed = desc.size.max_mips(desc.dimension).min(hal::MAX_MIP_LEVELS);
|
||||
if mips == 0 || mips > max_levels_allowed {
|
||||
return Err(CreateTextureError::InvalidMipLevelCount {
|
||||
requested: mips,
|
||||
maximum: max_levels_allowed,
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let (width_multiple, height_multiple) = desc.format.size_multiple_requirement();
|
||||
let (mut width_multiple, mut height_multiple) = desc.format.size_multiple_requirement();
|
||||
|
||||
if desc.format.is_multi_planar_format() {
|
||||
// TODO(https://github.com/gfx-rs/wgpu/issues/8491): fix
|
||||
// `mip_level_size` calculation for these formats and relax this
|
||||
// restriction.
|
||||
width_multiple <<= desc.mip_level_count.saturating_sub(1);
|
||||
height_multiple <<= desc.mip_level_count.saturating_sub(1);
|
||||
}
|
||||
|
||||
if desc.size.width % width_multiple != 0 {
|
||||
return Err(CreateTextureError::InvalidDimension(
|
||||
@ -1456,15 +1473,6 @@ impl Device {
|
||||
};
|
||||
}
|
||||
|
||||
let mips = desc.mip_level_count;
|
||||
let max_levels_allowed = desc.size.max_mips(desc.dimension).min(hal::MAX_MIP_LEVELS);
|
||||
if mips == 0 || mips > max_levels_allowed {
|
||||
return Err(CreateTextureError::InvalidMipLevelCount {
|
||||
requested: mips,
|
||||
maximum: max_levels_allowed,
|
||||
});
|
||||
}
|
||||
|
||||
let missing_allowed_usages = match desc.format.planes() {
|
||||
Some(planes) => {
|
||||
let mut planes_usages = wgt::TextureUsages::all();
|
||||
|
||||
@ -158,6 +158,56 @@ fn test_compute_render_extent() {
|
||||
let _ = desc.compute_render_extent(0, None);
|
||||
}
|
||||
}
|
||||
|
||||
for format in [wgpu::TextureFormat::NV12, wgpu::TextureFormat::P010] {
|
||||
let desc = wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width: 8,
|
||||
height: 4,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 2,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format,
|
||||
usage: wgpu::TextureUsages::empty(),
|
||||
view_formats: &[],
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
desc.compute_render_extent(0, Some(0)),
|
||||
wgpu::Extent3d {
|
||||
width: 8,
|
||||
height: 4,
|
||||
depth_or_array_layers: 1,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
desc.compute_render_extent(0, Some(1)),
|
||||
wgpu::Extent3d {
|
||||
width: 4,
|
||||
height: 2,
|
||||
depth_or_array_layers: 1,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
desc.compute_render_extent(1, Some(0)),
|
||||
wgpu::Extent3d {
|
||||
width: 4,
|
||||
height: 2,
|
||||
depth_or_array_layers: 1,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
desc.compute_render_extent(1, Some(1)),
|
||||
wgpu::Extent3d {
|
||||
width: 2,
|
||||
height: 1,
|
||||
depth_or_array_layers: 1,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_texture_format_string_size() -> usize {
|
||||
|
||||
@ -2881,6 +2881,20 @@ impl TextureFormat {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the subsampling factor for the indicated plane of a multi-planar format.
|
||||
#[must_use]
|
||||
pub fn subsampling_factors(&self, plane: Option<u32>) -> (u32, u32) {
|
||||
match *self {
|
||||
Self::NV12 | Self::P010 => match plane {
|
||||
Some(0) => (1, 1),
|
||||
Some(1) => (2, 2),
|
||||
Some(plane) => unreachable!("plane {plane} is not valid for {self:?}"),
|
||||
None => unreachable!("the plane must be specified for multi-planar formats"),
|
||||
},
|
||||
_ => (1, 1),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the format has a color aspect
|
||||
#[must_use]
|
||||
pub fn has_color_aspect(&self) -> bool {
|
||||
@ -2910,6 +2924,10 @@ impl TextureFormat {
|
||||
}
|
||||
|
||||
/// Returns the size multiple requirement for a texture using this format.
|
||||
///
|
||||
/// `create_texture` currently enforces a stricter restriction than this for
|
||||
/// mipmapped multi-planar formats.
|
||||
/// TODO(<https://github.com/gfx-rs/wgpu/issues/8491>): Remove this note.
|
||||
#[must_use]
|
||||
pub fn size_multiple_requirement(&self) -> (u32, u32) {
|
||||
match *self {
|
||||
@ -6186,9 +6204,17 @@ impl Extent3d {
|
||||
}
|
||||
|
||||
/// Calculates the extent at a given mip level.
|
||||
/// Does *not* account for memory size being a multiple of block size.
|
||||
///
|
||||
/// This is a low-level helper for internal use.
|
||||
///
|
||||
/// It does *not* account for memory size being a multiple of block size.
|
||||
///
|
||||
/// TODO(<https://github.com/gfx-rs/wgpu/issues/8491>): It also does not
|
||||
/// consider whether an even dimension is required due to chroma
|
||||
/// subsampling, but it probably should.
|
||||
///
|
||||
/// <https://gpuweb.github.io/gpuweb/#logical-miplevel-specific-texture-extent>
|
||||
#[doc(hidden)]
|
||||
#[must_use]
|
||||
pub fn mip_level_size(&self, level: u32, dim: TextureDimension) -> Self {
|
||||
Self {
|
||||
@ -6459,20 +6485,26 @@ impl<L, V> TextureDescriptor<L, V> {
|
||||
|
||||
/// Computes the render extent of this texture.
|
||||
///
|
||||
/// This is a low-level helper exported for use by wgpu-core.
|
||||
///
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-compute-render-extent>
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If the mip level is out of range.
|
||||
#[doc(hidden)]
|
||||
#[must_use]
|
||||
pub fn compute_render_extent(&self, mip_level: u32, plane: Option<u32>) -> Extent3d {
|
||||
let width = self.size.width >> mip_level;
|
||||
let height = self.size.height >> mip_level;
|
||||
let Extent3d {
|
||||
width,
|
||||
height,
|
||||
depth_or_array_layers: _,
|
||||
} = self.mip_level_size(mip_level).expect("invalid mip level");
|
||||
|
||||
let (width, height) = match (self.format, plane) {
|
||||
(TextureFormat::NV12 | TextureFormat::P010, Some(0)) => (width, height),
|
||||
(TextureFormat::NV12 | TextureFormat::P010, Some(1)) => (width / 2, height / 2),
|
||||
_ => {
|
||||
debug_assert!(!self.format.is_multi_planar_format());
|
||||
(width, height)
|
||||
}
|
||||
};
|
||||
let (w_subsampling, h_subsampling) = self.format.subsampling_factors(plane);
|
||||
|
||||
let width = width / w_subsampling;
|
||||
let height = height / h_subsampling;
|
||||
|
||||
Extent3d {
|
||||
width,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user