|
1 | 1 | //! Tests for texture copy
|
2 | 2 |
|
| 3 | +use wgpu::*; |
3 | 4 | use wgpu_test::{gpu_test, GpuTestConfiguration};
|
4 | 5 |
|
5 | 6 | #[gpu_test]
|
@@ -228,3 +229,109 @@ static WRITE_TEXTURE_NO_OOB: GpuTestConfiguration =
|
228 | 229 | },
|
229 | 230 | );
|
230 | 231 | });
|
| 232 | + |
| 233 | +// Test a writeTexture operation that will use the staging buffer. |
| 234 | +// If run with the address sanitizer, this serves as a regression |
| 235 | +// test for https://github.com/gfx-rs/wgpu/pull/7893. |
| 236 | +#[gpu_test] |
| 237 | +static WRITE_TEXTURE_VIA_STAGING_BUFFER: GpuTestConfiguration = GpuTestConfiguration::new() |
| 238 | + .run_async(|ctx| async move { |
| 239 | + let width = 89; |
| 240 | + let height = 17; |
| 241 | + |
| 242 | + let tex = ctx.device.create_texture(&TextureDescriptor { |
| 243 | + label: None, |
| 244 | + dimension: TextureDimension::D2, |
| 245 | + size: Extent3d { |
| 246 | + width, |
| 247 | + height, |
| 248 | + depth_or_array_layers: 1, |
| 249 | + }, |
| 250 | + format: TextureFormat::R8Uint, |
| 251 | + usage: TextureUsages::COPY_DST |
| 252 | + | TextureUsages::COPY_SRC |
| 253 | + | TextureUsages::TEXTURE_BINDING, |
| 254 | + mip_level_count: 1, |
| 255 | + sample_count: 1, |
| 256 | + view_formats: &[], |
| 257 | + }); |
| 258 | + |
| 259 | + let write_width: u32 = 31; |
| 260 | + let write_height: u32 = 5; |
| 261 | + let write_bytes_per_row: u32 = 113; |
| 262 | + let write_data = (0..(write_height - 1) * write_bytes_per_row + write_width) |
| 263 | + .map(|b| (b % 256) as u8) |
| 264 | + .collect::<Vec<_>>(); |
| 265 | + |
| 266 | + ctx.queue.write_texture( |
| 267 | + TexelCopyTextureInfo { |
| 268 | + texture: &tex, |
| 269 | + mip_level: 0, |
| 270 | + origin: Origin3d::ZERO, |
| 271 | + aspect: TextureAspect::All, |
| 272 | + }, |
| 273 | + &write_data, |
| 274 | + TexelCopyBufferLayout { |
| 275 | + offset: 0, |
| 276 | + bytes_per_row: Some(write_bytes_per_row), |
| 277 | + rows_per_image: Some(19), |
| 278 | + }, |
| 279 | + Extent3d { |
| 280 | + width: write_width, |
| 281 | + height: write_height, |
| 282 | + depth_or_array_layers: 1, |
| 283 | + }, |
| 284 | + ); |
| 285 | + |
| 286 | + ctx.queue.submit(None); |
| 287 | + |
| 288 | + let read_bytes_per_row = wgt::COPY_BYTES_PER_ROW_ALIGNMENT; |
| 289 | + let read_buffer = ctx.device.create_buffer(&BufferDescriptor { |
| 290 | + label: None, |
| 291 | + size: (height * read_bytes_per_row) as u64, |
| 292 | + usage: BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST, |
| 293 | + mapped_at_creation: false, |
| 294 | + }); |
| 295 | + |
| 296 | + let mut encoder = ctx |
| 297 | + .device |
| 298 | + .create_command_encoder(&CommandEncoderDescriptor { label: None }); |
| 299 | + |
| 300 | + encoder.copy_texture_to_buffer( |
| 301 | + TexelCopyTextureInfo { |
| 302 | + texture: &tex, |
| 303 | + mip_level: 0, |
| 304 | + origin: Origin3d::ZERO, |
| 305 | + aspect: TextureAspect::All, |
| 306 | + }, |
| 307 | + TexelCopyBufferInfo { |
| 308 | + buffer: &read_buffer, |
| 309 | + layout: TexelCopyBufferLayout { |
| 310 | + offset: 0, |
| 311 | + bytes_per_row: Some(read_bytes_per_row), |
| 312 | + rows_per_image: Some(height), |
| 313 | + }, |
| 314 | + }, |
| 315 | + Extent3d { |
| 316 | + width, |
| 317 | + height, |
| 318 | + depth_or_array_layers: 1, |
| 319 | + }, |
| 320 | + ); |
| 321 | + |
| 322 | + ctx.queue.submit(Some(encoder.finish())); |
| 323 | + |
| 324 | + let slice = read_buffer.slice(..); |
| 325 | + slice.map_async(MapMode::Read, |_| ()); |
| 326 | + ctx.async_poll(PollType::wait()).await.unwrap(); |
| 327 | + let read_data: Vec<u8> = slice.get_mapped_range().to_vec(); |
| 328 | + |
| 329 | + for x in 0..write_width { |
| 330 | + for y in 0..write_height { |
| 331 | + assert_eq!( |
| 332 | + read_data[(y * read_bytes_per_row + x) as usize], |
| 333 | + write_data[(y * write_bytes_per_row + x) as usize] |
| 334 | + ); |
| 335 | + } |
| 336 | + } |
| 337 | + }); |
0 commit comments