Test for use of staging buffer in writeTexture (#7963)

This commit is contained in:
Andy Leiserson 2025-07-17 15:52:51 -07:00 committed by GitHub
parent 9a596fa1dc
commit 5d14f33259
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,5 +1,6 @@
//! Tests for texture copy
use wgpu::*;
use wgpu_test::{gpu_test, GpuTestConfiguration};
#[gpu_test]
@ -228,3 +229,109 @@ static WRITE_TEXTURE_NO_OOB: GpuTestConfiguration =
},
);
});
// Test a writeTexture operation that will use the staging buffer.
// If run with the address sanitizer, this serves as a regression
// test for https://github.com/gfx-rs/wgpu/pull/7893.
#[gpu_test]
static WRITE_TEXTURE_VIA_STAGING_BUFFER: GpuTestConfiguration = GpuTestConfiguration::new()
.run_async(|ctx| async move {
let width = 89;
let height = 17;
let tex = ctx.device.create_texture(&TextureDescriptor {
label: None,
dimension: TextureDimension::D2,
size: Extent3d {
width,
height,
depth_or_array_layers: 1,
},
format: TextureFormat::R8Uint,
usage: TextureUsages::COPY_DST
| TextureUsages::COPY_SRC
| TextureUsages::TEXTURE_BINDING,
mip_level_count: 1,
sample_count: 1,
view_formats: &[],
});
let write_width: u32 = 31;
let write_height: u32 = 5;
let write_bytes_per_row: u32 = 113;
let write_data = (0..(write_height - 1) * write_bytes_per_row + write_width)
.map(|b| (b % 256) as u8)
.collect::<Vec<_>>();
ctx.queue.write_texture(
TexelCopyTextureInfo {
texture: &tex,
mip_level: 0,
origin: Origin3d::ZERO,
aspect: TextureAspect::All,
},
&write_data,
TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(write_bytes_per_row),
rows_per_image: Some(19),
},
Extent3d {
width: write_width,
height: write_height,
depth_or_array_layers: 1,
},
);
ctx.queue.submit(None);
let read_bytes_per_row = wgt::COPY_BYTES_PER_ROW_ALIGNMENT;
let read_buffer = ctx.device.create_buffer(&BufferDescriptor {
label: None,
size: (height * read_bytes_per_row) as u64,
usage: BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let mut encoder = ctx
.device
.create_command_encoder(&CommandEncoderDescriptor { label: None });
encoder.copy_texture_to_buffer(
TexelCopyTextureInfo {
texture: &tex,
mip_level: 0,
origin: Origin3d::ZERO,
aspect: TextureAspect::All,
},
TexelCopyBufferInfo {
buffer: &read_buffer,
layout: TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(read_bytes_per_row),
rows_per_image: Some(height),
},
},
Extent3d {
width,
height,
depth_or_array_layers: 1,
},
);
ctx.queue.submit(Some(encoder.finish()));
let slice = read_buffer.slice(..);
slice.map_async(MapMode::Read, |_| ());
ctx.async_poll(PollType::wait()).await.unwrap();
let read_data: Vec<u8> = slice.get_mapped_range().to_vec();
for x in 0..write_width {
for y in 0..write_height {
assert_eq!(
read_data[(y * read_bytes_per_row + x) as usize],
write_data[(y * write_bytes_per_row + x) as usize]
);
}
}
});