fix(gsplat): release ImageBitmap memory after streamed SOG texture upload#8758
Merged
Conversation
SOG textures loaded via the gsplat octree retained their source ImageBitmap on Texture._levels for the texture's lifetime, holding decoded pixel data long after the GPU had its own copy. Close ImageBitmaps on Texture.destroy() generically, and add an opt-in release-after-upload path used by octree-managed SOG textures and the octree environment resource, both of which are re-created from scratch on device loss and therefore don't need the CPU source retained.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR reduces memory retention for streamed gsplat SOG textures by ensuring decoded ImageBitmap sources don’t remain referenced on Texture._levels after the GPU upload is complete, and by adding an explicit opt-in path for resources that are re-created on device loss.
Changes:
- Add
Texture.releaseImageSources()/Texture.setReleaseSourceAfterUpload()and wire them into WebGL/WebGPU upload paths. - Ensure
Texture.destroy()closes anyImageBitmapsources still referenced by_levels. - Expose
GSplatSogResource.releaseTextureSources()and invoke it from the unified gsplat octree / octree instance when resources become device-loss-recreatable.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/scene/gsplat/gsplat-sog-resource.js | Adds a helper to opt SOG-owned textures into releasing ImageBitmap sources after upload. |
| src/scene/gsplat-unified/gsplat-octree.js | Calls the resource helper on file resource arrival to allow early source release. |
| src/scene/gsplat-unified/gsplat-octree-instance.js | Calls the resource helper once environment placement exists (device-loss teardown guaranteed). |
| src/platform/graphics/webgpu/webgpu-texture.js | Releases opted-in ImageBitmap sources after WebGPU upload completes. |
| src/platform/graphics/webgl/webgl-texture.js | Releases opted-in ImageBitmap sources after WebGL upload completes. |
| src/platform/graphics/texture.js | Implements the new source-release API and closes ImageBitmap sources during texture destruction. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+358
to
362
| // Free CPU-side decoded pixel data; the GPU has its own copy after upload. | ||
| this.releaseImageSources(); | ||
|
|
||
| this._levels = null; | ||
| this.device = null; |
Comment on lines
+400
to
+404
| setReleaseSourceAfterUpload() { | ||
| this.releaseSourceAfterUpload = true; | ||
|
|
||
| // If upload has already happened, release eagerly. | ||
| if (!this._needsUpload && !this._needsMipmapsUpload) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SOG textures loaded via the gsplat octree retained their source ImageBitmap on
Texture._levelsfor the texture's lifetime, holding fully-decoded pixel data long after the GPU had its own copy of the texture. ImageBitmap storage is implementation-defined (CPU, GPU, or shared memory depending on browser and platform), but in all cases it sits in memory untilclose()is called — wasteful for streamed gsplat scenes that load many SOG files over time.Changes:
_levelswhen a Texture is destroyed_onDeviceLostis guaranteed to dump the resourceMemory: