-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't mark a previous mesh transform as changed if it didn't actually change. #17688
Conversation
change. This patch fixes a bug whereby we're re-extracting every mesh every frame. It's a regression from PR bevyengine#17413. The code in question has actually been in the tree with this bug for quite a while; it's that just the code didn't actually run unless the renderer considered the previous view transforms necessary. Occlusion culling expanded the set of circumstances under which Bevy computes the previous view transforms, causing this bug to appear more often. This patch fixes the issue by checking to see if the previous transform of a mesh actually differs from the current transform before copying the current transform to the previous transform.
// Make sure not to trigger change detection on | ||
// `PreviousGlobalTransform` if the previous transform hasn't | ||
// changed. | ||
if old_previous_transform != Some(&new_previous_transform) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC there's a way to skip change detection while letting you still mutate the component directly instead of reinserting. I don't know if it would have a significant perf impact on this though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would still need to potentially insert because the mesh might not have a PreviousGlobalTransform
to begin with.
Wasm CI issues should be resolved once you upstream from |
PR bevyengine#17688 broke motion vector computation, and therefore motion blur, because it enabled retention of `MeshInputUniform`s, and `MeshInputUniform`s contain the indices of the previous frame's transform and the previous frame's skinned mesh joint matrices. On frame N, if a `MeshInputUniform` is retained on GPU from the previous frame, the `previous_input_index` and `previous_skin_index` would refer to the indices for frame N - 2, not the index for frame N - 1. This patch fixes the problems. It solves these issues in two different ways, one for transforms and one for skins: 1. To fix transforms, this patch supplies the *frame index* to the shader as part of the view uniforms, and specifies which frame index each mesh's previous transform refers to. So, in the situation described above, the frame index would be N, the previous frame index would be N - 1, and the `previous_input_frame_number` would be N - 2. The shader can now detect this situation and infer that the mesh has been retained, and can therefore conclude that the mesh's transform hasn't changed. 2. To fix skins, this patch replaces the explicit `previous_skin_index` with an invariant that the index of the joints for the current frame and the index of the joints for the previous frame are the same. This means that the `MeshInputUniform` never has to be updated even if the skin is animated. The downside is that we have to copy joint matrices from the previous frame's buffer to the current frame's buffer in `extract_skins`. The rationale behind (2) is that we currently have no mechanism to detect when joints that affect a skin have been updated, short of comparing all the transforms and setting a flag for `extract_meshes_for_gpu_building` to consume, which would regress performance as we want `extract_skins` and `extract_meshes_for_gpu_building` to be able to run in parallel. To test this change, use `cargo run --example motion_blur`.
… change. (bevyengine#17688) This patch fixes a bug whereby we're re-extracting every mesh every frame. It's a regression from PR bevyengine#17413. The code in question has actually been in the tree with this bug for quite a while; it's that just the code didn't actually run unless the renderer considered the previous view transforms necessary. Occlusion culling expanded the set of circumstances under which Bevy computes the previous view transforms, causing this bug to appear more often. This patch fixes the issue by checking to see if the previous transform of a mesh actually differs from the current transform before copying the current transform to the previous transform.
PR #17688 broke motion vector computation, and therefore motion blur, because it enabled retention of `MeshInputUniform`s, and `MeshInputUniform`s contain the indices of the previous frame's transform and the previous frame's skinned mesh joint matrices. On frame N, if a `MeshInputUniform` is retained on GPU from the previous frame, the `previous_input_index` and `previous_skin_index` would refer to the indices for frame N - 2, not the index for frame N - 1. This patch fixes the problems. It solves these issues in two different ways, one for transforms and one for skins: 1. To fix transforms, this patch supplies the *frame index* to the shader as part of the view uniforms, and specifies which frame index each mesh's previous transform refers to. So, in the situation described above, the frame index would be N, the previous frame index would be N - 1, and the `previous_input_frame_number` would be N - 2. The shader can now detect this situation and infer that the mesh has been retained, and can therefore conclude that the mesh's transform hasn't changed. 2. To fix skins, this patch replaces the explicit `previous_skin_index` with an invariant that the index of the joints for the current frame and the index of the joints for the previous frame are the same. This means that the `MeshInputUniform` never has to be updated even if the skin is animated. The downside is that we have to copy joint matrices from the previous frame's buffer to the current frame's buffer in `extract_skins`. The rationale behind (2) is that we currently have no mechanism to detect when joints that affect a skin have been updated, short of comparing all the transforms and setting a flag for `extract_meshes_for_gpu_building` to consume, which would regress performance as we want `extract_skins` and `extract_meshes_for_gpu_building` to be able to run in parallel. To test this change, use `cargo run --example motion_blur`.
This patch fixes a bug whereby we're re-extracting every mesh every frame. It's a regression from PR #17413. The code in question has actually been in the tree with this bug for quite a while; it's that just the code didn't actually run unless the renderer considered the previous view transforms necessary. Occlusion culling expanded the set of circumstances under which Bevy computes the previous view transforms, causing this bug to appear more often.
This patch fixes the issue by checking to see if the previous transform of a mesh actually differs from the current transform before copying the current transform to the previous transform.