-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathAvatarTransformMatrixJobWrapper.cs
More file actions
113 lines (91 loc) · 4.52 KB
/
AvatarTransformMatrixJobWrapper.cs
File metadata and controls
113 lines (91 loc) · 4.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
using System;
using DCL.AvatarRendering.AvatarShape.ComputeShader;
using DCL.AvatarRendering.AvatarShape.UnityInterface;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
namespace DCL.AvatarRendering.AvatarShape.Components
{
public class AvatarTransformMatrixJobWrapper : IDisposable
{
// Each task processes one full avatar (62 bone multiplies). Small batch count keeps
// worker utilisation high without excessive scheduling overhead.
private const int BONE_MATRIX_BATCH_COUNT = 4;
internal const int AVATAR_ARRAY_SIZE = 100;
private const int BONES_ARRAY_LENGTH = ComputeShaderConstants.BONE_COUNT;
private const int BONES_PER_AVATAR_LENGTH = AVATAR_ARRAY_SIZE * BONES_ARRAY_LENGTH;
private bool disposed;
// Placeholder transform for released or unassigned slots in the TAAs.
private readonly Transform dummyTransform;
private readonly MainPlayerPipeline mainPlayerAvatar;
private readonly RemoteAvatarPipeline remoteAvatars;
public NativeArray<float4x4> MainPlayerBonesResult => mainPlayerAvatar.Job.BonesMatricesResult;
public NativeArray<float4x4> RemoteAvatarsBonesResult => remoteAvatars.Job.BonesMatricesResult;
#if UNITY_INCLUDE_TESTS
public int MatrixFromAllAvatarsLength => remoteAvatars.MatrixFromAllAvatarsLength;
public int UpdateAvatarLength => remoteAvatars.UpdateAvatarLength;
public int CurrentAvatarAmountSupported => remoteAvatars.CurrentAvatarAmountSupported;
#endif
public AvatarTransformMatrixJobWrapper()
{
var dummyGO = new GameObject("AvatarTransformMatrixDummy") { hideFlags = HideFlags.HideAndDontSave };
dummyTransform = dummyGO.transform;
remoteAvatars = new RemoteAvatarPipeline(AVATAR_ARRAY_SIZE, BONES_ARRAY_LENGTH, BONES_PER_AVATAR_LENGTH, dummyTransform);
mainPlayerAvatar = new MainPlayerPipeline(BONES_ARRAY_LENGTH);
}
/// <summary>
/// Schedules bone gather + matrix calculation for all avatars.
/// The main player pipeline is completed immediately so its transforms are unlocked
/// before InterpolateCharacterSystem runs.
/// </summary>
public void ScheduleBoneMatrixCalculation()
{
mainPlayerAvatar.ScheduleAndComplete();
remoteAvatars.Schedule(BONE_MATRIX_BATCH_COUNT);
}
public void CompleteBoneMatrixCalculations()
{
remoteAvatars.Complete();
}
/// <summary>
/// Registers the main player avatar into a dedicated pipeline whose transforms
/// are gathered and released before the remote batch, preventing TransformAccessArray
/// locks from blocking InterpolateCharacterSystem.
/// </summary>
/// <summary>
/// Registers from a local (pre-Add) component. Sets index and flag on the component
/// so the caller can pass it into World.Add already registered.
/// </summary>
public void RegisterMainPlayerAvatar(AvatarBase avatarBase, ref AvatarTransformMatrixComponent transformMatrixComponent)
{
transformMatrixComponent.IndexInGlobalJobArray = GlobalJobArrayIndex.ValidUnsafe(0);
transformMatrixComponent.IsMainPlayer = true;
mainPlayerAvatar.Register(avatarBase.transform, transformMatrixComponent.bones.Inner);
}
/// <summary>
/// Registers a remote avatar for bone matrix calculation.
/// Subsequent calls for already-registered avatars are no-ops; per-frame work is handled by the gather jobs.
/// </summary>
public void RegisterAvatar(AvatarBase avatarBase, ref AvatarTransformMatrixComponent transformMatrixComponent)
{
remoteAvatars.Register(avatarBase, ref transformMatrixComponent);
}
public void Dispose()
{
remoteAvatars.Complete();
remoteAvatars.Dispose();
mainPlayerAvatar.Dispose();
if (dummyTransform != null)
UnityEngine.Object.Destroy(dummyTransform.gameObject);
disposed = true;
}
public void ReleaseAvatar(ref AvatarTransformMatrixComponent avatarTransformMatrixComponent)
{
if (disposed) return;
//Main player avatar never gets released
if (avatarTransformMatrixComponent.IsMainPlayer)
return;
remoteAvatars.Release(ref avatarTransformMatrixComponent);
}
}
}