Skip to content

Rebuild bind group when its dynamic uniform buffer is re-allocated mid-frame#8906

Merged
mvaligursky merged 2 commits into
mainfrom
mv-bindgroup-dynamic-ubo-rebuild
Jun 15, 2026
Merged

Rebuild bind group when its dynamic uniform buffer is re-allocated mid-frame#8906
mvaligursky merged 2 commits into
mainfrom
mv-bindgroup-dynamic-ubo-rebuild

Conversation

@mvaligursky

Copy link
Copy Markdown
Contributor

Summary

A non-persistent uniform buffer is allocated from a per-frame dynamic (ring) buffer, and its underlying GPU buffer can change mid-frame. When the same bind group is re-baked multiple times in one frame — as the WebGPU XR multiview pass does (it replays the per-view bind groups once per view) — the buffer can move more than once per frame.

BindGroup.update() detected such a move via the per-frame renderVersion (renderVersionUpdated < uniformBuffer.renderVersionDirty). Since renderVersion is constant within a frame, this only catches the first move per frame. A later move left the bind group's GPU resource pointing at the old buffer while its dynamic offset advanced into the new one, so it sampled the wrong data.

Symptom: in the WebGPU test > xr-views example, the last (most-rotated) multiview view rendered with another view's matrices, shifting as the camera moved.

Fix

Compare the uniform buffer's allocation.gpuBuffer directly per non-persistent slot and rebuild the bind group whenever it changes — catching every move within a frame, not just the first. Persistent buffers never move and are skipped. The now-unused UniformBuffer.renderVersionDirty is removed.

The change stays in the generic BindGroup/UniformBuffer layer (no backend-specific access); the texture change-detection path is untouched.

Testing

  • npm test — all passing
  • npm run build:types — clean
  • Verified on the WebGPU test > xr-views example: all 4 multiview views now render correctly and remain correct under camera/pivot motion. WebGL unaffected.

🤖 Generated with Claude Code

…d-frame

A non-persistent uniform buffer is allocated from a per-frame dynamic buffer and can move to a different GPU buffer - possibly several times within one frame when the same bind group is re-baked repeatedly (e.g. the WebGPU XR multiview pass replays the view bind groups per view). BindGroup detected this via a per-frame renderVersion, which only catches the first move per frame, so a later move left the bind group referencing a stale GPU buffer while its dynamic offset advanced, reading the wrong data (visibly: an XR view rendered with another view's matrices).

Fix by comparing the uniform buffer's allocation.gpuBuffer directly and rebuilding whenever it changes. Removes the now-unused UniformBuffer.renderVersionDirty.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a WebGPU bind group correctness issue when non-persistent uniform buffers (allocated from per-frame dynamic/ring buffers) move to a different underlying GPU buffer multiple times within a single frame (notably in XR multiview), ensuring bind groups are rebuilt on every such move.

Changes:

  • Remove UniformBuffer.renderVersionDirty and its mid-frame move tracking based on per-frame renderVersion.
  • Track the last allocation.gpuBuffer per uniform-buffer slot in BindGroup and mark the bind group dirty whenever a non-persistent uniform buffer’s container changes.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/platform/graphics/uniform-buffer.js Removes renderVersionDirty-based tracking for dynamic uniform buffer moves.
src/platform/graphics/bind-group.js Adds per-slot dynamic-buffer container tracking to force bind group rebuilds on every mid-frame reallocation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/platform/graphics/bind-group.js Outdated
Addresses PR review: allocation.gpuBuffer is a DynamicBuffer (per DynamicBufferAllocation), so use the concrete type instead of object[] for better type generation and editor hints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mvaligursky mvaligursky merged commit 3e5aff9 into main Jun 15, 2026
9 checks passed
@mvaligursky mvaligursky deleted the mv-bindgroup-dynamic-ubo-rebuild branch June 15, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants