Skip to content

Fix WebGPU crashes from disposed geometry in indirect rendering#1062

Merged
braedonsaunders merged 1 commit into
mainfrom
claude/fix-threejs-render-dark-1mQfk
Jan 27, 2026
Merged

Fix WebGPU crashes from disposed geometry in indirect rendering#1062
braedonsaunders merged 1 commit into
mainfrom
claude/fix-threejs-render-dark-1mQfk

Conversation

@braedonsaunders

Copy link
Copy Markdown
Owner

Summary

This PR fixes WebGPU crashes caused by disposed geometry being used in indirect rendering. The issue occurs when source geometries are disposed while cloned geometries still reference their buffers, causing "setIndexBuffer" errors and rendering crashes.

Key Changes

  • Force GPU buffer recreation for cloned attributes: Set needsUpdate = true on cloned geometry attributes and indices to ensure WebGPU creates fresh GPU buffers instead of lazily sharing buffers with the source geometry.

  • Add pre-render validation: Introduced updateMeshVisibility() call in the render loop (after culling, before rendering) to catch disposed geometry before it causes WebGPU crashes.

  • Enhance disposed geometry detection: Improved validation logic in updateMeshVisibility() to detect when index buffers have been disposed (by checking if the array becomes null) and mark meshes as invalid before rendering.

  • Better error tracking: Added debug warnings when geometry is detected as invalid during visibility updates for easier troubleshooting.

Implementation Details

The root cause was that Three.js geometry cloning could create references to the same underlying GPU buffers as the source geometry. When the source geometry was disposed elsewhere, these buffers became invalid, but the cloned geometry still tried to use them. By explicitly setting needsUpdate = true on cloned attributes, we force WebGPU to allocate new buffers.

The pre-render validation acts as a safety net to catch any remaining edge cases where disposed geometry slips through, preventing crashes and providing diagnostic information.

https://claude.ai/code/session_01E36JDY27fQMf5EzB3KMZD4

The Three.js render would go dark after ~7 minutes of gameplay due to
WebGPU failing to set the index buffer on GPURenderPassEncoder.

Root cause: When GPUIndirectRenderer cloned geometry attributes, the
cloned buffers weren't immediately marked as needing update. WebGPU
would lazily create GPU buffers, potentially sharing them with the
source geometry. When UnitRenderer disposed inactive instanced meshes
after INACTIVE_MESH_CLEANUP_FRAMES, the shared GPU buffers would be
invalidated, causing the cloned geometry to reference invalid buffers.

Fix:
1. Mark cloned attributes and index buffers as needsUpdate=true in
   GPUIndirectRenderer.createIndirectMesh() to force fresh GPU buffer
   creation
2. Add per-frame validation in updateMeshVisibility() to catch disposed
   geometry before rendering
3. Call updateMeshVisibility() every frame in UnitRenderer after
   culling to ensure invalid meshes are hidden before the render pass

https://claude.ai/code/session_01E36JDY27fQMf5EzB3KMZD4
@braedonsaunders braedonsaunders merged commit 19bce04 into main Jan 27, 2026
4 checks passed
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