From 2f80d081bc8b1d122f2b11ad3eb3d03a09ae8116 Mon Sep 17 00:00:00 2001 From: Greeble <166992735+greeble-dev@users.noreply.github.com> Date: Sun, 6 Apr 2025 18:51:22 +0100 Subject: [PATCH] Fix `many_foxes` + motion blur = crash on WebGL (#18715) ## Objective Fix #18714. ## Solution Make sure `SkinUniforms::prev_buffer` is resized at the same time as `current_buffer`. There will be a one frame visual glitch when the buffers are resized, since `prev_buffer` is incorrectly initialised with the current joint transforms. Note that #18074 includes the same fix. I'm assuming this smaller PR will land first. ## Testing See repro instructions in #18714. Tested on `animated_mesh`, `many_foxes`, `custom_skinned_mesh`, Win10/Nvidia with Vulkan, WebGL/Chrome, WebGPU/Chrome. --- crates/bevy_pbr/src/render/skin.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/render/skin.rs b/crates/bevy_pbr/src/render/skin.rs index bec846a038..af33371261 100644 --- a/crates/bevy_pbr/src/render/skin.rs +++ b/crates/bevy_pbr/src/render/skin.rs @@ -211,7 +211,7 @@ pub fn prepare_skins( // Swap current and previous buffers. mem::swap(&mut uniform.current_buffer, &mut uniform.prev_buffer); - // Resize the buffer if necessary. Include extra space equal to `MAX_JOINTS` + // Resize the buffers if necessary. Include extra space equal to `MAX_JOINTS` // because we need to be able to bind a full uniform buffer's worth of data // if skins use uniform buffers on this platform. let needed_size = (uniform.current_staging_buffer.len() as u64 + MAX_JOINTS as u64) @@ -223,7 +223,7 @@ pub fn prepare_skins( new_size += new_size / 2; } - // Create a new buffer. + // Create the new buffers. let buffer_usages = if skins_use_uniform_buffers(&render_device) { BufferUsages::UNIFORM } else { @@ -235,6 +235,24 @@ pub fn prepare_skins( size: new_size, mapped_at_creation: false, }); + uniform.prev_buffer = render_device.create_buffer(&BufferDescriptor { + label: Some("skin uniform buffer"), + usage: buffer_usages, + size: new_size, + mapped_at_creation: false, + }); + + // We've created a new `prev_buffer` but we don't have the previous joint + // data needed to fill it out correctly. Use the current joint data + // instead. + // + // TODO: This is a bug - will cause motion blur to ignore joint movement + // for one frame. + render_queue.write_buffer( + &uniform.prev_buffer, + 0, + bytemuck::must_cast_slice(&uniform.current_staging_buffer[..]), + ); } // Write the data from `uniform.current_staging_buffer` into