@@ -235,96 +235,88 @@ pub(crate) fn validate_linear_texture_data(
235235 copy_size : & Extent3d ,
236236 need_copy_aligned_rows : bool ,
237237) -> 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 {
254265 return Err ( TransferError :: UnalignedCopyWidth ) ;
255266 }
256- if copy_height % block_height != 0 {
267+ if copy_height % block_height_texels != 0 {
257268 return Err ( TransferError :: UnalignedCopyHeight ) ;
258269 }
259270
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 ;
264273
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 {
268277 return Err ( TransferError :: InvalidBytesPerRow ) ;
269278 }
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 {
280286 return Err ( TransferError :: InvalidRowsPerImage ) ;
281287 }
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 ) ;
288290 } ;
289291
290292 if need_copy_aligned_rows {
291293 let bytes_per_row_alignment = wgt:: COPY_BYTES_PER_ROW_ALIGNMENT as BufferAddress ;
292294
293- let mut offset_alignment = block_size ;
295+ let mut offset_alignment = block_size_bytes ;
294296 if format. is_depth_stencil_format ( ) {
295297 offset_alignment = 4
296298 }
297299 if offset % offset_alignment != 0 {
298300 return Err ( TransferError :: UnalignedBufferOffset ( offset) ) ;
299301 }
300302
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 {
302306 return Err ( TransferError :: UnalignedBytesPerRow ) ;
303307 }
304308 }
305309
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 {
319311 return Err ( TransferError :: BufferOverrun {
320312 start_offset : offset,
321- end_offset : offset + required_bytes_in_copy ,
313+ end_offset : offset + bytes_in_copy ,
322314 buffer_size,
323315 side : buffer_side,
324316 } ) ;
325317 }
326318
327- Ok ( ( required_bytes_in_copy , bytes_per_image ) )
319+ Ok ( ( bytes_in_copy , image_stride_bytes ) )
328320}
329321
330322/// WebGPU's [validating texture copy range][vtcr] algorithm.
0 commit comments