@@ -235,96 +235,88 @@ pub(crate) fn validate_linear_texture_data(
235
235
copy_size : & Extent3d ,
236
236
need_copy_aligned_rows : bool ,
237
237
) -> Result < ( BufferAddress , BufferAddress ) , TransferError > {
238
- // Convert all inputs to BufferAddress (u64) to avoid some of the overflow issues
239
- // Note: u64 is not always enough to prevent overflow, especially when multiplying
240
- // something with a potentially large depth value, so it is preferable to validate
241
- // the copy size before calling this function (for example via `validate_texture_copy_range`).
242
- let copy_width = copy_size. width as BufferAddress ;
243
- let copy_height = copy_size. height as BufferAddress ;
244
- let depth_or_array_layers = copy_size. depth_or_array_layers as BufferAddress ;
245
-
246
- let offset = layout. offset ;
247
-
248
- let block_size = format. block_copy_size ( Some ( aspect) ) . unwrap ( ) as BufferAddress ;
249
- let ( block_width, block_height) = format. block_dimensions ( ) ;
250
- let block_width = block_width as BufferAddress ;
251
- let block_height = block_height as BufferAddress ;
252
-
253
- if copy_width % block_width != 0 {
238
+ let wgt:: BufferTextureCopyInfo {
239
+ copy_width,
240
+ copy_height,
241
+ depth_or_array_layers,
242
+
243
+ offset,
244
+
245
+ block_size_bytes,
246
+ block_width_texels,
247
+ block_height_texels,
248
+
249
+ width_blocks : _,
250
+ height_blocks,
251
+
252
+ row_bytes_dense,
253
+ row_stride_bytes,
254
+
255
+ image_stride_rows : _,
256
+ image_stride_bytes,
257
+
258
+ image_rows_dense : _,
259
+ image_bytes_dense : _,
260
+
261
+ bytes_in_copy,
262
+ } = layout. get_buffer_texture_copy_info ( format, aspect, copy_size) ;
263
+
264
+ if copy_width % block_width_texels != 0 {
254
265
return Err ( TransferError :: UnalignedCopyWidth ) ;
255
266
}
256
- if copy_height % block_height != 0 {
267
+ if copy_height % block_height_texels != 0 {
257
268
return Err ( TransferError :: UnalignedCopyHeight ) ;
258
269
}
259
270
260
- let width_in_blocks = copy_width / block_width;
261
- let height_in_blocks = copy_height / block_height;
262
-
263
- let bytes_in_last_row = width_in_blocks * block_size;
271
+ let requires_multiple_rows = depth_or_array_layers > 1 || height_blocks > 1 ;
272
+ let requires_multiple_images = depth_or_array_layers > 1 ;
264
273
265
- let bytes_per_row = if let Some ( bytes_per_row ) = layout. bytes_per_row {
266
- let bytes_per_row = bytes_per_row as BufferAddress ;
267
- if bytes_per_row < bytes_in_last_row {
274
+ if let Some ( raw_bytes_per_row ) = layout. bytes_per_row {
275
+ let raw_bytes_per_row = raw_bytes_per_row as BufferAddress ;
276
+ if raw_bytes_per_row < row_bytes_dense {
268
277
return Err ( TransferError :: InvalidBytesPerRow ) ;
269
278
}
270
- bytes_per_row
271
- } else {
272
- if depth_or_array_layers > 1 || height_in_blocks > 1 {
273
- return Err ( TransferError :: UnspecifiedBytesPerRow ) ;
274
- }
275
- 0
276
- } ;
277
- let rows_per_image = if let Some ( rows_per_image) = layout. rows_per_image {
278
- let rows_per_image = rows_per_image as BufferAddress ;
279
- if rows_per_image < height_in_blocks {
279
+ } else if requires_multiple_rows {
280
+ return Err ( TransferError :: UnspecifiedBytesPerRow ) ;
281
+ }
282
+
283
+ if let Some ( raw_rows_per_image) = layout. rows_per_image {
284
+ let raw_rows_per_image = raw_rows_per_image as BufferAddress ;
285
+ if raw_rows_per_image < height_blocks {
280
286
return Err ( TransferError :: InvalidRowsPerImage ) ;
281
287
}
282
- rows_per_image
283
- } else {
284
- if depth_or_array_layers > 1 {
285
- return Err ( TransferError :: UnspecifiedRowsPerImage ) ;
286
- }
287
- 0
288
+ } else if requires_multiple_images {
289
+ return Err ( TransferError :: UnspecifiedRowsPerImage ) ;
288
290
} ;
289
291
290
292
if need_copy_aligned_rows {
291
293
let bytes_per_row_alignment = wgt:: COPY_BYTES_PER_ROW_ALIGNMENT as BufferAddress ;
292
294
293
- let mut offset_alignment = block_size ;
295
+ let mut offset_alignment = block_size_bytes ;
294
296
if format. is_depth_stencil_format ( ) {
295
297
offset_alignment = 4
296
298
}
297
299
if offset % offset_alignment != 0 {
298
300
return Err ( TransferError :: UnalignedBufferOffset ( offset) ) ;
299
301
}
300
302
301
- if bytes_per_row % bytes_per_row_alignment != 0 {
303
+ // The alignment of row_stride_bytes is only required if there are
304
+ // multiple rows
305
+ if requires_multiple_rows && row_stride_bytes % bytes_per_row_alignment != 0 {
302
306
return Err ( TransferError :: UnalignedBytesPerRow ) ;
303
307
}
304
308
}
305
309
306
- let bytes_per_image = bytes_per_row * rows_per_image;
307
-
308
- let required_bytes_in_copy = if depth_or_array_layers == 0 {
309
- 0
310
- } else {
311
- let mut required_bytes_in_copy = bytes_per_image * ( depth_or_array_layers - 1 ) ;
312
- if height_in_blocks > 0 {
313
- required_bytes_in_copy += bytes_per_row * ( height_in_blocks - 1 ) + bytes_in_last_row;
314
- }
315
- required_bytes_in_copy
316
- } ;
317
-
318
- if offset + required_bytes_in_copy > buffer_size {
310
+ if offset + bytes_in_copy > buffer_size {
319
311
return Err ( TransferError :: BufferOverrun {
320
312
start_offset : offset,
321
- end_offset : offset + required_bytes_in_copy ,
313
+ end_offset : offset + bytes_in_copy ,
322
314
buffer_size,
323
315
side : buffer_side,
324
316
} ) ;
325
317
}
326
318
327
- Ok ( ( required_bytes_in_copy , bytes_per_image ) )
319
+ Ok ( ( bytes_in_copy , image_stride_bytes ) )
328
320
}
329
321
330
322
/// WebGPU's [validating texture copy range][vtcr] algorithm.
0 commit comments