MeshQueue.cs
4.16 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using System.Collections.Generic;
using UnityEngine.XR.ARSubsystems;
using LegacyMeshId = UnityEngine.XR.MeshId;
namespace UnityEngine.XR.ARFoundation
{
internal class MeshInfoComparer : IComparer<MeshInfo>
{
/// <summary>
/// Mesh infos are stored last first so that the dequeue operation is fast
/// - < 0 <paramref name="infoA"/> will appear before infoB in the list
/// - 0 <paramref name="infoA"/> has the same priority as <paramref name="infoB"/>
/// - > 0 <paramref name="infoB"/> will appear before infoA in the list
/// </summary>
public int Compare(MeshInfo infoA, MeshInfo infoB)
{
// Prioritize 'added' over 'updated'
if (infoA.ChangeState < infoB.ChangeState)
{
return 1;
}
else if (infoB.ChangeState < infoA.ChangeState)
{
return -1;
}
else
{
// If 'A' has a high priority, then we return a positive number
// which puts A last in the list. This means we can dequeue
// the next mesh to generate by taking the last element.
return (infoA.PriorityHint - infoB.PriorityHint);
}
}
}
internal class MeshQueue
{
public void EnqueueUnique(MeshInfo meshInfo)
{
if (m_MeshSet.Contains(meshInfo.MeshId))
{
UpdateExisting(meshInfo);
}
else
{
InsertNew(meshInfo);
}
}
public int count
{
get { return m_Queue.Count; }
}
public bool TryDequeue(IReadOnlyDictionary<LegacyMeshId, MeshInfo> generating, out MeshInfo meshInfo)
{
for (int i = m_Queue.Count - 1; i >= 0; --i)
{
meshInfo = m_Queue[i];
if (!generating.ContainsKey(meshInfo.MeshId))
{
m_Queue.RemoveAt(i);
m_MeshSet.Remove(meshInfo.MeshId);
return true;
}
}
meshInfo = default;
return false;
}
public bool Remove(LegacyMeshId meshId)
{
// It is relatively rare to remove an existing mesh
// (this means it was removed while awaiting generation).
// So it most cases we should be able to early out.
if (!m_MeshSet.Remove(meshId))
return false;
// Otherwise, perform a linear search and remove it.
for (int i = 0; i < m_Queue.Count; ++i)
{
if (m_Queue[i].MeshId.Equals(meshId))
{
m_Queue.RemoveAt(i);
break;
}
}
return true;
}
void InsertNew(MeshInfo meshInfo)
{
int index = m_Queue.BinarySearch(meshInfo, s_MeshInfoComparer);
if (index < 0)
index = ~index;
m_Queue.Insert(index, meshInfo);
m_MeshSet.Add(meshInfo.MeshId);
}
void UpdateExisting(MeshInfo meshInfo)
{
for (int i = 0; i < m_Queue.Count; ++i)
{
var existing = m_Queue[i];
if (existing.MeshId.Equals(meshInfo.MeshId))
{
// Only need to do anything if they are not equal
if (existing.PriorityHint != meshInfo.PriorityHint)
{
existing.PriorityHint = meshInfo.PriorityHint;
m_Queue[i] = existing;
m_Queue.Sort(s_MeshInfoComparer);
}
break;
}
}
}
public void Clear()
{
m_Queue.Clear();
m_MeshSet.Clear();
}
// This list is kept sorted according to MeshInfoComparer
List<MeshInfo> m_Queue = new List<MeshInfo>();
HashSet<LegacyMeshId> m_MeshSet = new HashSet<LegacyMeshId>();
MeshInfoComparer s_MeshInfoComparer = new MeshInfoComparer();
}
}