Skip to content

Commit c5554a9

Browse files
committed
Yield to the defer agent per mesh assignment during instantiation
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.
1 parent 4fe3391 commit c5554a9

2 files changed

Lines changed: 21 additions & 6 deletions

File tree

Packages/com.unity.cloud.gltfast/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Fixed
10+
- Frame budget overruns during scene instantiation of nodes with many mesh assignments: the hierarchy population now yields to the defer agent per mesh assignment, not only per node.
11+
12+
## [6.19.0] - 2026-05-19
13+
914
### Added
1015
- (Add-Ons) Import glTF animations to custom animation systems.
1116
- [IAnimationProcessor](xref:GLTFast.Animations.IAnimationProcessor) — animation clips conversion

Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfImport.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3003,10 +3003,10 @@ async Task InstantiateSceneInternal(IInstantiator instantiator, int sceneId, Can
30033003
}
30043004
}
30053005

3006-
async Task IterateNodes(uint nodeIndex, uint? parentIndex, Action<uint, uint?> callback)
3006+
async Task IterateNodes(uint nodeIndex, uint? parentIndex, Func<uint, uint?, Task> callback)
30073007
{
30083008
var node = this.Root.Nodes[(int)nodeIndex];
3009-
callback(nodeIndex, parentIndex);
3009+
await callback(nodeIndex, parentIndex);
30103010
await DeferAgent.BreakPoint();
30113011
if (node.children != null)
30123012
{
@@ -3045,10 +3045,8 @@ void CreateHierarchy(uint nodeIndex, uint? parentIndex)
30453045
Profiler.EndSample();
30463046
}
30473047

3048-
void PopulateHierarchy(uint nodeIndex, uint? parentIndex)
3048+
async Task PopulateHierarchy(uint nodeIndex, uint? parentIndex)
30493049
{
3050-
3051-
Profiler.BeginSample("PopulateHierarchy");
30523050
var node = this.Root.Nodes[(int)nodeIndex];
30533051

30543052
if (node.mesh >= 0)
@@ -3057,6 +3055,11 @@ void PopulateHierarchy(uint nodeIndex, uint? parentIndex)
30573055
foreach (var meshAssignment in m_MeshAssignments.Values(node.mesh))
30583056
{
30593057
cancellationToken.ThrowIfCancellationRequestedWithTracking();
3058+
// A node can carry many mesh assignments (one per primitive cluster of a
3059+
// multi-material mesh). Populating all of them in one un-yielding callback
3060+
// can far exceed the defer agent's frame budget
3061+
// => yield per assignment, like the node iteration above does per node.
3062+
Profiler.BeginSample("PopulateHierarchy");
30603063

30613064
var mesh = meshAssignment.mesh;
30623065
var meshName = string.IsNullOrEmpty(mesh.name) ? null : mesh.name;
@@ -3151,9 +3154,12 @@ void PopulateHierarchy(uint nodeIndex, uint? parentIndex)
31513154
}
31523155

31533156
meshNumeration++;
3157+
Profiler.EndSample();
3158+
await DeferAgent.BreakPoint();
31543159
}
31553160
}
31563161

3162+
Profiler.BeginSample("PopulateHierarchy");
31573163
if (node.camera >= 0
31583164
&& Root.Cameras != null
31593165
&& node.camera < Root.Cameras.Count
@@ -3185,7 +3191,11 @@ void PopulateHierarchy(uint nodeIndex, uint? parentIndex)
31853191
foreach (var nodeId in scene.nodes)
31863192
{
31873193
cancellationToken.ThrowIfCancellationRequestedWithTracking();
3188-
await IterateNodes(nodeId, null, CreateHierarchy);
3194+
await IterateNodes(nodeId, null, (index, parent) =>
3195+
{
3196+
CreateHierarchy(index, parent);
3197+
return Task.CompletedTask;
3198+
});
31893199
}
31903200
foreach (var nodeId in scene.nodes)
31913201
{

0 commit comments

Comments
 (0)