blob: c54a5c3a690b90840950f6fcfa75a46e79643176 (
plain)
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
|
using Unity.Collections.LowLevel.Unsafe;
using Unity.Mathematics;
using UnityEngine;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
namespace Pathfinding.Drawing {
using static CommandBuilder;
[BurstCompile]
internal struct PersistentFilterJob : IJob {
[NativeDisableUnsafePtrRestriction]
public unsafe UnsafeAppendBuffer* buffer;
public float time;
public void Execute () {
var stackPersist = new NativeArray<bool>(GeometryBuilderJob.MaxStackSize, Allocator.Temp, NativeArrayOptions.ClearMemory);
var stackScope = new NativeArray<int>(GeometryBuilderJob.MaxStackSize, Allocator.Temp, NativeArrayOptions.ClearMemory);
unsafe {
// Store in local variables for performance (makes it possible to use registers for a lot of fields)
var bufferPersist = *buffer;
long writeOffset = 0;
long readOffset = 0;
bool shouldWrite = false;
int stackSize = 0;
long lastNonMetaWrite = -1;
while (readOffset < bufferPersist.Length) {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
UnityEngine.Assertions.Assert.IsTrue(readOffset + UnsafeUtility.SizeOf<Command>() <= bufferPersist.Length);
#endif
var cmd = *(Command*)((byte*)bufferPersist.Ptr + readOffset);
var cmdBit = 1 << ((int)cmd & 0xFF);
bool isMeta = (cmdBit & StreamSplitter.MetaCommands) != 0;
int size = StreamSplitter.CommandSizes[(int)cmd & 0xFF] + ((cmd & Command.PushColorInline) != 0 ? UnsafeUtility.SizeOf<Color32>() : 0);
if ((cmd & (Command)0xFF) == Command.Text) {
// Very pretty way of reading the TextData struct right after the command label and optional Color32
var data = *((TextData*)((byte*)bufferPersist.Ptr + readOffset + size) - 1);
// Add the size of the embedded string in the buffer
size += data.numCharacters * UnsafeUtility.SizeOf<System.UInt16>();
} else if ((cmd & (Command)0xFF) == Command.Text3D) {
// Very pretty way of reading the TextData struct right after the command label and optional Color32
var data = *((TextData3D*)((byte*)bufferPersist.Ptr + readOffset + size) - 1);
// Add the size of the embedded string in the buffer
size += data.numCharacters * UnsafeUtility.SizeOf<System.UInt16>();
}
#if ENABLE_UNITY_COLLECTIONS_CHECKS
UnityEngine.Assertions.Assert.IsTrue(readOffset + size <= bufferPersist.Length);
UnityEngine.Assertions.Assert.IsTrue(writeOffset + size <= bufferPersist.Length);
#endif
if (shouldWrite || isMeta) {
if (!isMeta) lastNonMetaWrite = writeOffset;
if (writeOffset != readOffset) {
// We need to use memmove instead of memcpy because the source and destination regions may overlap
UnsafeUtility.MemMove((byte*)bufferPersist.Ptr + writeOffset, (byte*)bufferPersist.Ptr + readOffset, size);
}
writeOffset += size;
}
if ((cmdBit & StreamSplitter.PushCommands) != 0) {
if ((cmd & (Command)0xFF) == Command.PushPersist) {
// Very pretty way of reading the PersistData struct right after the command label and optional Color32
// (even though a PushColorInline command is not usually combined with PushPersist)
var data = *((PersistData*)((byte*)bufferPersist.Ptr + readOffset + size) - 1);
// Scopes only survive if this condition is true
shouldWrite = time <= data.endTime;
}
stackScope[stackSize] = (int)(writeOffset - size);
stackPersist[stackSize] = shouldWrite;
stackSize++;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (stackSize >= GeometryBuilderJob.MaxStackSize) throw new System.Exception("Push commands are too deeply nested. This can happen if you have deeply nested WithMatrix or WithColor scopes.");
#else
if (stackSize >= GeometryBuilderJob.MaxStackSize) {
buffer->Length = 0;
return;
}
#endif
} else if ((cmdBit & StreamSplitter.PopCommands) != 0) {
stackSize--;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (stackSize < 0) throw new System.Exception("Trying to issue a pop command but there is no corresponding push command");
#else
if (stackSize < 0) {
buffer->Length = 0;
return;
}
#endif
// If a scope was pushed and later popped, but no actual draw commands were written to the buffers
// inside that scope then we erase the whole scope.
if ((int)lastNonMetaWrite < stackScope[stackSize]) {
writeOffset = (long)stackScope[stackSize];
}
shouldWrite = stackPersist[stackSize];
}
readOffset += size;
}
bufferPersist.Length = (int)writeOffset;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (stackSize != 0) throw new System.Exception("Inconsistent push/pop commands. Are your push and pop commands properly matched?");
#else
if (stackSize != 0) {
buffer->Length = 0;
return;
}
#endif
*buffer = bufferPersist;
}
}
}
}
|