perf(importer): parse each material once per mesh instead of per primitive #836
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!836
Loading…
Reference in a new issue
No description provided.
Delete branch "perf/gltf-import-texture-dedup"
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?
parse_models rebuilt a material's descriptors for every primitive in the
mesh, and parse_texture copies the whole pixel buffer. Primitives of one mesh
routinely share a material - a multi-material mesh, a mesh split into
primitives by attribute, or simply a character model - so an N-primitive mesh
with a shared material converted and copied the same textures N times.
Cache parsed materials per mesh, keyed by the material's index in the
document. A primitive with no material resolves to the default material, whose
index is None; that is still one shared cache entry, so unmaterialized
primitives benefit too.
Measured with a generated asset of N primitives sharing one material and two
1024x1024 textures (make_shared_material_asset), min of 25 runs:
primitives=1 2.58 ms -> 3.40 ms (unchanged within noise)
primitives=8 13.70 ms -> 9.10 ms
primitives=32 55.96 ms -> 25.20 ms
Interleaved A/B at 32 primitives gave 1.70-1.97x across repeats. The saving
scales with the primitive count and texture size, and is zero for a mesh whose
primitives all use distinct materials.
The cache holds a clone per entry and each model still receives its own copy,
so a later mutation of one model's material cannot affect another.
Adds a regression test with two primitives sharing a material and a third on a
different one built from different textures: the shared pair must come out
identical, and the third must not receive the cached material. Verified the
test fails if the cache is keyed so that distinct materials collide.
Note the remaining cost is the clone of the already-parsed descriptor per
model. Removing that would need the material held behind an Arc all the way
into the GPU upload path, which is a wider change across orbital_texture and
its consumers; this keeps the change local to the importer.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
ca2b90061bea47b26a5e