@@ -13,16 +13,15 @@ use bevy::{
13
13
prelude:: * ,
14
14
render:: {
15
15
camera:: RenderTarget ,
16
- render_asset:: RenderAssetUsages ,
17
- render_asset:: RenderAssets ,
16
+ render_asset:: { RenderAssetUsages , RenderAssets } ,
18
17
render_graph:: { self , NodeRunError , RenderGraph , RenderGraphContext , RenderLabel } ,
19
18
render_resource:: {
20
19
Buffer , BufferDescriptor , BufferUsages , CommandEncoderDescriptor , Extent3d ,
21
20
ImageCopyBuffer , ImageDataLayout , Maintain , MapMode , TextureDimension , TextureFormat ,
22
21
TextureUsages ,
23
22
} ,
24
23
renderer:: { RenderContext , RenderDevice , RenderQueue } ,
25
- texture:: BevyDefault ,
24
+ texture:: { BevyDefault , TextureFormatPixelInfo } ,
26
25
Extract , Render , RenderApp , RenderSet ,
27
26
} ,
28
27
} ;
@@ -361,6 +360,10 @@ impl render_graph::Node for ImageCopyDriver {
361
360
let block_dimensions = src_image. texture_format . block_dimensions ( ) ;
362
361
let block_size = src_image. texture_format . block_copy_size ( None ) . unwrap ( ) ;
363
362
363
+ // Calculating correct size of image row because
364
+ // copy_texture_to_buffer can copy image only by rows aligned wgpu::COPY_BYTES_PER_ROW_ALIGNMENT
365
+ // That's why image in buffer can be little bit wider
366
+ // This should be taken into account at copy from buffer stage
364
367
let padded_bytes_per_row = RenderDevice :: align_copy_bytes_per_row (
365
368
( src_image. size . x as usize / block_dimensions. 0 as usize ) * block_size as usize ,
366
369
) ;
@@ -492,7 +495,24 @@ fn update(
492
495
for image in images_to_save. iter ( ) {
493
496
// Fill correct data from channel to image
494
497
let img_bytes = images. get_mut ( image. id ( ) ) . unwrap ( ) ;
495
- img_bytes. data . clone_from ( & image_data) ;
498
+
499
+ // We need to ensure that this works regardless of the image dimensions
500
+ // If the image became wider when copying from the texture to the buffer,
501
+ // then the data is reduced to its original size when copying from the buffer to the image.
502
+ let row_bytes = img_bytes. width ( ) as usize
503
+ * img_bytes. texture_descriptor . format . pixel_size ( ) ;
504
+ let aligned_row_bytes = RenderDevice :: align_copy_bytes_per_row ( row_bytes) ;
505
+ if row_bytes == aligned_row_bytes {
506
+ img_bytes. data . clone_from ( & image_data) ;
507
+ } else {
508
+ // shrink data to original image size
509
+ img_bytes. data = image_data
510
+ . chunks ( aligned_row_bytes)
511
+ . take ( img_bytes. height ( ) as usize )
512
+ . flat_map ( |row| & row[ ..row_bytes. min ( row. len ( ) ) ] )
513
+ . cloned ( )
514
+ . collect ( ) ;
515
+ }
496
516
497
517
// Create RGBA Image Buffer
498
518
let img = match img_bytes. clone ( ) . try_into_dynamic ( ) {
0 commit comments