perf(importer): skip decoding glTF images no material references #835
No reviewers
Labels
No labels
Context: Bug
Context: Enhancements
Platform: Android
Platform: Linux
Platform: Web
Platform: Windows
Platform: iOS
Platform: macOS
Target: CI
Target: CLI
Target: Dependency
Target: Engine
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
SakulFlee/Orbital!835
Loading…
Reference in a new issue
No description provided.
Delete branch "perf/gltf-import-skip-unused-images"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The importer decoded every image in the document. Real-world glTF assets
routinely ship images that no material points at - leftover art, or textures
kept for a material variant that is not used - and each one costs decode time
plus a full pixel buffer held in RAM for the duration of the import, for data
nothing ever reads.
Decode only images referenced by a material's normal, base-color,
metallic-roughness, occlusion or emissive slot. The reference scan runs over
the whole document rather than the subset a request will visit, because
GltfImport::Specific is only resolved after the document and its images have
been loaded; decoding an image nothing ends up using is cheap, whereas missing
one a later stage needs would not be.
The image vector is now Vec<Optiongltf::image::Data>: unreferenced entries
stay in place as None so the positional lookups in parse_texture and friends,
which index by document image index, keep working. A new decoded_image helper
centralises the unwrap and panics with a clear message if a material ever
references an image the scan did not decode, which would be a bug rather than
bad input.
Measured on a generated asset with 4 unreferenced 1024x1024 textures
(make_unused_texture_asset), min of 20 runs: 5.53 ms -> 2.69 ms, ~1.4-2.4x
across repeats. The saving scales with the size and count of the unreferenced
images, and is zero for an asset where every image is referenced.
Adds two regression tests covering the external-file and embedded-GLB paths.
Both point the unreferenced image at non-decodable bytes, so they fail if the
image is decoded at all; verified they fail with the skip disabled.
Also fixes build_glb in the test helper, which only produced parseable files
by luck. The reader splits the JSON chunk at exactly its declared length and
passes it to serde, so the chunk length must be the 4-byte-aligned length (as
gltf's own Glb::to_writer emits) and the JSON padding must be spaces rather
than NULs, which serde rejects as trailing characters.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com