decentraland / decentraland/unity-explorer

[TECH DEBT] Primitive Meshes | Confirm no leak under memory pressure & extend shared-mesh reuse to boxes/planes

Open
#9,620 1 comment 0 reactions 0 assignees View on GitHub
2-medium graphics memory-issue performance tech debt
Dominant language
C#
Stars
23
Forks
17
Avg merge
2d 14h
Merged PRs (30d)
94

Description

### πŸ“Š **Priority Level:**
Medium

### πŸ“ **Area/Component:**
Primitive mesh rendering β€” `Utility.Primitives` (`BoxFactory`, `PlaneFactory`, `SphereFactory`, `PrimitivesUtility`) and `ECS.Unity.PrimitiveRenderer` (`SpherePrimitive`, mesh component pools registered in `PrimitivesRenderingPlugin`).

### πŸ“ **Description:**
Follow-up to #9614, which introduced a single shared immutable `Mesh` for spheres. Two open questions were deliberately left out of that PR's scope and should be validated/pursued separately:

1. **Confirm primitive meshes do not leak** and are reclaimed under memory pressure.
2. **Investigate whether the same shared-mesh reuse is applicable to boxes and planes** (and cylinders), not just spheres.

### πŸ” **Current State:**
- The sphere optimization relies on the fact that the primitive component pools register **no `actionOnDestroy`** (meshes are never `Destroy`ed) and the pool registry is a global singleton β€” so the shared sphere mesh intentionally lives for the app lifetime. This is safe for a single shared mesh, but it also means per-instance Box/Plane/Cylinder meshes are pooled/reused and never released under memory pressure. We have not verified their lifecycle against the memory-budgeting / cache-cleanup path.
- Boxes and planes still allocate one `Mesh` per entity because they *can* carry per-instance custom UVs (`PBMeshRenderer.Box.Uvs` / `.Plane.Uvs`). However, the **default** (no custom UVs) box/plane is geometrically identical across all instances β€” the same premise that made the sphere shareable. Those instances could share a single default mesh, with only custom-UV instances getting a private mesh.

### πŸ’‘ **Proposed Solution:**
1. **Leak/pressure audit:** Capture a Unity Memory Profiler snapshot (or reuse the benchmark scene deployed for #9614 β€” world `sdk7testscenes.dcl.eth` @ `40,40`) while spawning and destroying large primitive grids. Confirm Mesh assets are returned/reclaimed as scenes unload and under memory pressure, and that nothing (shared sphere mesh included) grows unbounded across teleports.
2. **Extend shared-mesh reuse:** Prototype a shared default mesh for boxes/planes (and cylinders) β€” share when no custom UVs are present, fall back to a per-instance mesh only when `Uvs` are supplied. Measure the Mesh-count reduction against the existing benchmark scene.

### βš–οΈ **Impact Assessment:**
#### Performance Impact:
Potential large reduction in Mesh asset count / native memory for scenes that spawn many default boxes/planes (mirrors the sphere win in #9614). Leak audit protects against unbounded growth across scene loads/teleports.

#### Maintainability Impact:
Consolidating on the shared-mesh pattern (already centralized via `PrimitivesUtility`) reduces per-factory divergence. Requires clear documentation of which primitives are shared vs per-instance and why.

#### Risk of Refactoring:
Medium. Sharing a mesh across box/plane instances requires guaranteeing the shared mesh is never mutated per instance (custom-UV path must branch to a private mesh). Getting the shared/immutable boundary wrong could cause cross-entity visual corruption. The leak audit itself is low risk (measurement only).

### πŸ“ˆ **Effort Estimate:**
M

### πŸ”— **Dependencies:**
- Builds on #9614 (shared sphere mesh; `PrimitivesUtility.ApplyUVs`).
- Benchmark scene: decentraland/sdk7-test-scenes#84 (deployed to world `sdk7testscenes.dcl.eth` @ `40,40`).

### πŸ–₯️ **Additional Notes:**
Use the `unity-memory-snapshot` tooling to parse `.snap` captures headlessly for the leak audit. Verify behavior specifically across scene unload and teleport, since that is where pooled-but-never-released meshes would accumulate.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.