mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
Fix validation of compressed mipmaps
This commit is contained in:
parent
8f430ab1ef
commit
19fb491262
@ -233,6 +233,13 @@ pub(crate) fn validate_texture_copy_range(
|
||||
let block_height = block_height as u32;
|
||||
|
||||
let mut extent = texture_dimension.level_extent(texture_copy_view.mip_level as u8);
|
||||
|
||||
// Adjust extent for the physical size of mips
|
||||
if texture_copy_view.mip_level != 0 {
|
||||
extent.width = conv::align_up(extent.width, block_width);
|
||||
extent.height = conv::align_up(extent.height, block_height);
|
||||
}
|
||||
|
||||
match texture_dimension {
|
||||
hal::image::Kind::D1(..) => {
|
||||
if (copy_size.height, copy_size.depth) != (1, 1) {
|
||||
@ -512,6 +519,17 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
))?
|
||||
}
|
||||
|
||||
// WebGPU uses the physical size of the texture for copies whereas vulkan uses
|
||||
// the virtual size. We have passed validation, so it's safe to use the
|
||||
// image extent data directly. We want the provided copy size to be no larger than
|
||||
// the virtual size.
|
||||
let max_image_extent = dst_texture.kind.level_extent(destination.mip_level as _);
|
||||
let image_extent = Extent3d {
|
||||
width: copy_size.width.min(max_image_extent.width),
|
||||
height: copy_size.height.min(max_image_extent.height),
|
||||
depth: copy_size.depth,
|
||||
};
|
||||
|
||||
let buffer_width = (source.layout.bytes_per_row / bytes_per_block) * block_width as u32;
|
||||
let region = hal::command::BufferImageCopy {
|
||||
buffer_offset: source.layout.offset,
|
||||
@ -519,7 +537,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
buffer_height: source.layout.rows_per_image,
|
||||
image_layers: dst_layers,
|
||||
image_offset: dst_offset,
|
||||
image_extent: conv::map_extent(copy_size, dst_texture.dimension),
|
||||
image_extent: conv::map_extent(&image_extent, dst_texture.dimension),
|
||||
};
|
||||
let cmb_raw = cmd_buf.raw.last_mut().unwrap();
|
||||
unsafe {
|
||||
@ -641,6 +659,17 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
))?
|
||||
}
|
||||
|
||||
// WebGPU uses the physical size of the texture for copies whereas vulkan uses
|
||||
// the virtual size. We have passed validation, so it's safe to use the
|
||||
// image extent data directly. We want the provided copy size to be no larger than
|
||||
// the virtual size.
|
||||
let max_image_extent = src_texture.kind.level_extent(source.mip_level as _);
|
||||
let image_extent = Extent3d {
|
||||
width: copy_size.width.min(max_image_extent.width),
|
||||
height: copy_size.height.min(max_image_extent.height),
|
||||
depth: copy_size.depth,
|
||||
};
|
||||
|
||||
let buffer_width =
|
||||
(destination.layout.bytes_per_row / bytes_per_block) * block_width as u32;
|
||||
let region = hal::command::BufferImageCopy {
|
||||
@ -649,7 +678,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
buffer_height: destination.layout.rows_per_image,
|
||||
image_layers: src_layers,
|
||||
image_offset: src_offset,
|
||||
image_extent: conv::map_extent(copy_size, src_texture.dimension),
|
||||
image_extent: conv::map_extent(&image_extent, src_texture.dimension),
|
||||
};
|
||||
let cmb_raw = cmd_buf.raw.last_mut().unwrap();
|
||||
unsafe {
|
||||
@ -765,12 +794,28 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
copy_size,
|
||||
)?;
|
||||
|
||||
// WebGPU uses the physical size of the texture for copies whereas vulkan uses
|
||||
// the virtual size. We have passed validation, so it's safe to use the
|
||||
// image extent data directly. We want the provided copy size to be no larger than
|
||||
// the virtual size.
|
||||
let max_src_image_extent = src_texture.kind.level_extent(source.mip_level as _);
|
||||
let max_dst_image_extent = dst_texture.kind.level_extent(destination.mip_level as _);
|
||||
let image_extent = Extent3d {
|
||||
width: copy_size
|
||||
.width
|
||||
.min(max_src_image_extent.width.min(max_dst_image_extent.width)),
|
||||
height: copy_size
|
||||
.height
|
||||
.min(max_src_image_extent.height.min(max_dst_image_extent.height)),
|
||||
depth: copy_size.depth,
|
||||
};
|
||||
|
||||
let region = hal::command::ImageCopy {
|
||||
src_subresource: src_layers,
|
||||
src_offset,
|
||||
dst_subresource: dst_layers,
|
||||
dst_offset,
|
||||
extent: conv::map_extent(copy_size, src_texture.dimension),
|
||||
extent: conv::map_extent(&image_extent, src_texture.dimension),
|
||||
};
|
||||
let cmb_raw = cmd_buf.raw.last_mut().unwrap();
|
||||
unsafe {
|
||||
|
@ -755,3 +755,16 @@ pub fn map_index_format(index_format: wgt::IndexFormat) -> hal::IndexType {
|
||||
wgt::IndexFormat::Uint32 => hal::IndexType::U32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Take `value` and round it up to the nearest alignment `alignment`.
|
||||
///
|
||||
/// ```text
|
||||
/// (0, 3) -> 0
|
||||
/// (1, 3) -> 3
|
||||
/// (2, 3) -> 3
|
||||
/// (3, 3) -> 3
|
||||
/// (4, 3) -> 6
|
||||
/// ...
|
||||
pub fn align_up(value: u32, alignment: u32) -> u32 {
|
||||
((value + alignment - 1) / alignment) * alignment
|
||||
}
|
||||
|
@ -409,13 +409,24 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
stage.memory.flush_range(&device.raw, 0, None)?;
|
||||
}
|
||||
|
||||
// WebGPU uses the physical size of the texture for copies whereas vulkan uses
|
||||
// the virtual size. We have passed validation, so it's safe to use the
|
||||
// image extent data directly. We want the provided copy size to be no larger than
|
||||
// the virtual size.
|
||||
let max_image_extent = dst.kind.level_extent(destination.mip_level as _);
|
||||
let image_extent = wgt::Extent3d {
|
||||
width: size.width.min(max_image_extent.width),
|
||||
height: size.height.min(max_image_extent.height),
|
||||
depth: size.depth,
|
||||
};
|
||||
|
||||
let region = hal::command::BufferImageCopy {
|
||||
buffer_offset: 0,
|
||||
buffer_width: (stage_bytes_per_row / bytes_per_block) * block_width,
|
||||
buffer_height: texel_rows_per_image,
|
||||
image_layers,
|
||||
image_offset,
|
||||
image_extent: conv::map_extent(size, dst.dimension),
|
||||
image_extent: conv::map_extent(&image_extent, dst.dimension),
|
||||
};
|
||||
unsafe {
|
||||
stage.cmdbuf.pipeline_barrier(
|
||||
|
Loading…
Reference in New Issue
Block a user