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,image_copy,texture_related:format:dimension="1d";*
|
||||||
webgpu:api,validation,queue,submit:command_buffer,*
|
webgpu:api,validation,queue,submit:command_buffer,*
|
||||||
webgpu:api,validation,render_pass,render_pass_descriptor:attachments,*
|
webgpu:api,validation,render_pass,render_pass_descriptor:attachments,*
|
||||||
webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,depthSlice,bound_check:*
|
webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,depthSlice,*
|
||||||
// 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:resolveTarget,*
|
webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,*
|
||||||
webgpu:api,validation,render_pass,resolve:resolve_attachment:*
|
webgpu:api,validation,render_pass,resolve:resolve_attachment:*
|
||||||
webgpu:api,validation,resource_usages,buffer,in_pass_encoder:*
|
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,resource_usages,texture,in_render_common:subresources,multiple_bind_groups:bg0Levels={"base":0,"count":1};*
|
||||||
webgpu:api,validation,texture,rg11b10ufloat_renderable:*
|
webgpu:api,validation,texture,rg11b10ufloat_renderable:*
|
||||||
webgpu:api,operation,render_pipeline,overrides:*
|
webgpu:api,operation,render_pipeline,overrides:*
|
||||||
|
webgpu:api,operation,rendering,3d_texture_slices:*
|
||||||
webgpu:api,operation,rendering,basic:clear:*
|
webgpu:api,operation,rendering,basic:clear:*
|
||||||
webgpu:api,operation,rendering,basic:fullscreen_quad:*
|
webgpu:api,operation,rendering,basic:fullscreen_quad:*
|
||||||
//FAIL: webgpu:api,operation,rendering,basic:large_draw:*
|
//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 {
|
if desc.size.width % width_multiple != 0 {
|
||||||
return Err(CreateTextureError::InvalidDimension(
|
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() {
|
let missing_allowed_usages = match desc.format.planes() {
|
||||||
Some(planes) => {
|
Some(planes) => {
|
||||||
let mut planes_usages = wgt::TextureUsages::all();
|
let mut planes_usages = wgt::TextureUsages::all();
|
||||||
|
|||||||
@ -158,6 +158,56 @@ fn test_compute_render_extent() {
|
|||||||
let _ = desc.compute_render_extent(0, None);
|
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 {
|
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
|
/// Returns `true` if the format has a color aspect
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn has_color_aspect(&self) -> bool {
|
pub fn has_color_aspect(&self) -> bool {
|
||||||
@ -2910,6 +2924,10 @@ impl TextureFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the size multiple requirement for a texture using this format.
|
/// 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]
|
#[must_use]
|
||||||
pub fn size_multiple_requirement(&self) -> (u32, u32) {
|
pub fn size_multiple_requirement(&self) -> (u32, u32) {
|
||||||
match *self {
|
match *self {
|
||||||
@ -6186,9 +6204,17 @@ impl Extent3d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the extent at a given mip level.
|
/// 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>
|
/// <https://gpuweb.github.io/gpuweb/#logical-miplevel-specific-texture-extent>
|
||||||
|
#[doc(hidden)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn mip_level_size(&self, level: u32, dim: TextureDimension) -> Self {
|
pub fn mip_level_size(&self, level: u32, dim: TextureDimension) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -6459,20 +6485,26 @@ impl<L, V> TextureDescriptor<L, V> {
|
|||||||
|
|
||||||
/// Computes the render extent of this texture.
|
/// 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>
|
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-compute-render-extent>
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// If the mip level is out of range.
|
||||||
|
#[doc(hidden)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn compute_render_extent(&self, mip_level: u32, plane: Option<u32>) -> Extent3d {
|
pub fn compute_render_extent(&self, mip_level: u32, plane: Option<u32>) -> Extent3d {
|
||||||
let width = self.size.width >> mip_level;
|
let Extent3d {
|
||||||
let height = self.size.height >> mip_level;
|
width,
|
||||||
|
height,
|
||||||
|
depth_or_array_layers: _,
|
||||||
|
} = self.mip_level_size(mip_level).expect("invalid mip level");
|
||||||
|
|
||||||
let (width, height) = match (self.format, plane) {
|
let (w_subsampling, h_subsampling) = self.format.subsampling_factors(plane);
|
||||||
(TextureFormat::NV12 | TextureFormat::P010, Some(0)) => (width, height),
|
|
||||||
(TextureFormat::NV12 | TextureFormat::P010, Some(1)) => (width / 2, height / 2),
|
let width = width / w_subsampling;
|
||||||
_ => {
|
let height = height / h_subsampling;
|
||||||
debug_assert!(!self.format.is_multi_planar_format());
|
|
||||||
(width, height)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Extent3d {
|
Extent3d {
|
||||||
width,
|
width,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user