Skip to content

Yield to the defer agent per mesh assignment during instantiation - #823

Closed
nickdnk wants to merge 1 commit into
atteneder:openupmfrom
nickdnk:slice-instantiation-per-mesh-assignment
Closed

Yield to the defer agent per mesh assignment during instantiation#823
nickdnk wants to merge 1 commit into
atteneder:openupmfrom
nickdnk:slice-instantiation-per-mesh-assignment

Conversation

@nickdnk

@nickdnk nickdnk commented Jul 15, 2026

Copy link
Copy Markdown

Same kind of performance related issue as #822 - if you have one very big object (say you are not the author and cannot easily split it), its instantiation can cause a stutter. Instantiation already yields to the frame budget per node, but a single node with many mesh assignments (multi-material meshes) populates them all in one go. This yields per assignment too, tunable by the existing frame budget logic.

Note: Everything below AI generated.

Problem

InstantiateSceneInternal honors the defer agent's frame budget between nodes (IterateNodes awaits BreakPoint() per node), but PopulateHierarchy populates all of a node's mesh assignments in one un-yielding callback. A node with many assignments (any multi-material mesh; CAD/archviz-style content routinely has dozens per node) blows the frame budget with no way for the defer agent to intervene.

Fix

Make the population callback Task-returning and yield DeferAgent.BreakPoint() after each mesh assignment — the same contract node iteration already follows, one level finer. The PopulateHierarchy profiler sample now wraps one assignment instead of a whole node, so captures attribute per assignment.

No public API change (the callback is a local function). Under UninterruptedDeferAgent, BreakPoint() is a no-op and behavior is byte-identical.

Measurements

Unity 6000.5.3f1, macOS (Apple Silicon), Mono development player, streaming scenes with high-node-count glbs (up to ~40 primitive clusters per node):

before after
worst PopulateHierarchy sample 70.5 ms 0.15 ms
worst instantiation-driven frame 76-95 ms within the defer agent's budget

Behavior notes for review

  • Instantiation was already non-atomic under a budgeted defer agent (per-node yields); this makes the granularity finer, so a multi-material object can render some submeshes a frame or two before the rest. Same class of intermediate state as before, one level deeper.
  • Cancellation can now land between a node's assignments; callers already own partial-scene teardown on cancel, so no new obligation.
  • Assignment order, meshNumeration, and the EndScene timing (where skins/animations bind) are unchanged.

Hierarchy population honored the frame budget only between nodes; a
node carrying many mesh assignments (multi-material meshes) populated
them all in one un-yielding callback (measured: 70 ms frames on large
scenes, 0.15 ms max after). No public API change; behavior identical
under UninterruptedDeferAgent.
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.

1 participant