Skip to content

Commit 2aed777

Browse files
bugsweeperalice-i-cecilemockersf
authored
Fixed incorrect behaviour of headless_renderer depending on image dimensions (#13388)
# Objective - Fixes #13384 . ## Solution - If the image became wider when copying from the texture to the buffer, then the data is reduced to its original size when copying from the buffer to the image. ## Testing - Ran example with 1919x1080 resolution ![000](https://github.com/bevyengine/bevy/assets/17225606/47d95ed7-1c8c-4be4-a45a-1f485a3d6aa7) --------- Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: François Mockers <[email protected]>
1 parent bf2aced commit 2aed777

File tree

1 file changed

+24
-4
lines changed

1 file changed

+24
-4
lines changed

examples/app/headless_renderer.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,15 @@ use bevy::{
1313
prelude::*,
1414
render::{
1515
camera::RenderTarget,
16-
render_asset::RenderAssetUsages,
17-
render_asset::RenderAssets,
16+
render_asset::{RenderAssetUsages, RenderAssets},
1817
render_graph::{self, NodeRunError, RenderGraph, RenderGraphContext, RenderLabel},
1918
render_resource::{
2019
Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d,
2120
ImageCopyBuffer, ImageDataLayout, Maintain, MapMode, TextureDimension, TextureFormat,
2221
TextureUsages,
2322
},
2423
renderer::{RenderContext, RenderDevice, RenderQueue},
25-
texture::BevyDefault,
24+
texture::{BevyDefault, TextureFormatPixelInfo},
2625
Extract, Render, RenderApp, RenderSet,
2726
},
2827
};
@@ -361,6 +360,10 @@ impl render_graph::Node for ImageCopyDriver {
361360
let block_dimensions = src_image.texture_format.block_dimensions();
362361
let block_size = src_image.texture_format.block_copy_size(None).unwrap();
363362

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
364367
let padded_bytes_per_row = RenderDevice::align_copy_bytes_per_row(
365368
(src_image.size.x as usize / block_dimensions.0 as usize) * block_size as usize,
366369
);
@@ -492,7 +495,24 @@ fn update(
492495
for image in images_to_save.iter() {
493496
// Fill correct data from channel to image
494497
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+
}
496516

497517
// Create RGBA Image Buffer
498518
let img = match img_bytes.clone().try_into_dynamic() {

0 commit comments

Comments
 (0)