@ifc-lite/geometry 3.5.0 → 3.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/diagnostics.d.ts +20 -0
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +18 -0
- package/dist/diagnostics.js.map +1 -1
- package/dist/geometry-coordinate.d.ts.map +1 -1
- package/dist/geometry-coordinate.js +19 -34
- package/dist/geometry-coordinate.js.map +1 -1
- package/dist/geometry-fingerprints.d.ts +114 -0
- package/dist/geometry-fingerprints.d.ts.map +1 -0
- package/dist/geometry-fingerprints.js +114 -0
- package/dist/geometry-fingerprints.js.map +1 -0
- package/dist/geometry-native.d.ts +26 -3
- package/dist/geometry-native.d.ts.map +1 -1
- package/dist/geometry-native.js +82 -11
- package/dist/geometry-native.js.map +1 -1
- package/dist/geometry-parallel.d.ts +34 -0
- package/dist/geometry-parallel.d.ts.map +1 -1
- package/dist/geometry-parallel.js +132 -53
- package/dist/geometry-parallel.js.map +1 -1
- package/dist/geometry.worker.d.ts +19 -8
- package/dist/geometry.worker.d.ts.map +1 -1
- package/dist/geometry.worker.js +96 -61
- package/dist/geometry.worker.js.map +1 -1
- package/dist/ifc-lite-bridge.d.ts +2 -0
- package/dist/ifc-lite-bridge.d.ts.map +1 -1
- package/dist/ifc-lite-bridge.js +4 -0
- package/dist/ifc-lite-bridge.js.map +1 -1
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -78
- package/dist/index.js.map +1 -1
- package/dist/native-bridge-conversion.d.ts.map +1 -1
- package/dist/native-bridge-conversion.js +42 -8
- package/dist/native-bridge-conversion.js.map +1 -1
- package/dist/packed-geometry-decoder.d.ts.map +1 -1
- package/dist/packed-geometry-decoder.js +17 -0
- package/dist/packed-geometry-decoder.js.map +1 -1
- package/dist/types.d.ts +67 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/wasm-asset-error.d.ts.map +1 -1
- package/dist/wasm-asset-error.js +6 -2
- package/dist/wasm-asset-error.js.map +1 -1
- package/dist/wasm-instance-free.d.ts +12 -0
- package/dist/wasm-instance-free.d.ts.map +1 -0
- package/dist/wasm-instance-free.js +41 -0
- package/dist/wasm-instance-free.js.map +1 -0
- package/dist/wasm-runtime-trap.d.ts.map +1 -1
- package/dist/wasm-runtime-trap.js +5 -2
- package/dist/wasm-runtime-trap.js.map +1 -1
- package/dist/wasm-shared-module.d.ts.map +1 -1
- package/dist/wasm-shared-module.js +7 -1
- package/dist/wasm-shared-module.js.map +1 -1
- package/package.json +3 -3
package/dist/geometry-native.js
CHANGED
|
@@ -49,8 +49,8 @@ export function enqueueNativeStreamingEvent(queuedEvents, event, queueState) {
|
|
|
49
49
|
queueState.queuedMeshes += event.meshes.length;
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
|
-
* Shared native streaming generator used by
|
|
53
|
-
* path-based
|
|
52
|
+
* Shared native streaming generator used by every native geometry route:
|
|
53
|
+
* buffer-based (`processStreaming`), path-based and cache-based.
|
|
54
54
|
*
|
|
55
55
|
* @param startStream Callback that kicks off the native stream and
|
|
56
56
|
* returns a promise resolving when it finishes.
|
|
@@ -58,8 +58,11 @@ export function enqueueNativeStreamingEvent(queuedEvents, event, queueState) {
|
|
|
58
58
|
* @param coordinator CoordinateHandler for incremental bounds.
|
|
59
59
|
* @param setLastNativeStats Callback to persist the latest stats on
|
|
60
60
|
* the owning GeometryProcessor instance.
|
|
61
|
+
* @param options Per-route queue/coordinate behaviour; see NativeStreamOptions.
|
|
61
62
|
*/
|
|
62
|
-
export async function* streamNativeGeometry(startStream, totalEstimate, coordinator, setLastNativeStats) {
|
|
63
|
+
export async function* streamNativeGeometry(startStream, totalEstimate, coordinator, setLastNativeStats, options = {}) {
|
|
64
|
+
const coalesce = options.coalesce !== false;
|
|
65
|
+
const processMeshes = options.processMeshes ?? ((meshes) => coordinator.processTrustedMeshesIncremental(meshes));
|
|
63
66
|
coordinator.reset();
|
|
64
67
|
yield { type: 'start', totalEstimate };
|
|
65
68
|
await yieldToEventLoop();
|
|
@@ -78,13 +81,21 @@ export async function* streamNativeGeometry(startStream, totalEstimate, coordina
|
|
|
78
81
|
resolvePending = null;
|
|
79
82
|
}
|
|
80
83
|
};
|
|
84
|
+
const enqueue = (event) => {
|
|
85
|
+
if (coalesce) {
|
|
86
|
+
enqueueNativeStreamingEvent(queuedEvents, event, queueState);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
queuedEvents.push(event);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
81
92
|
const streamingPromise = startStream({
|
|
82
93
|
onBatch: (batch) => {
|
|
83
|
-
|
|
94
|
+
enqueue({ type: 'batch', meshes: batch.meshes, nativeTelemetry: batch.nativeTelemetry });
|
|
84
95
|
wake();
|
|
85
96
|
},
|
|
86
97
|
onColorUpdate: (updates) => {
|
|
87
|
-
|
|
98
|
+
enqueue({ type: 'colorUpdate', updates: new Map(updates) });
|
|
88
99
|
wake();
|
|
89
100
|
},
|
|
90
101
|
onComplete: (stats) => {
|
|
@@ -100,6 +111,35 @@ export async function* streamNativeGeometry(startStream, totalEstimate, coordina
|
|
|
100
111
|
wake();
|
|
101
112
|
},
|
|
102
113
|
});
|
|
114
|
+
// A `startStream` rejection that never reached `onError` used to strand this
|
|
115
|
+
// generator: `completed` stays false, so the drain loop parks on the wake
|
|
116
|
+
// promise below and nothing ever resolves it — the load hangs forever and the
|
|
117
|
+
// failure surfaces only as an unhandled rejection. That is reachable today,
|
|
118
|
+
// because the bridge only routes throws through `onError` from inside its own
|
|
119
|
+
// try/catch: `NativeBridge.processGeometryStreamingPath` has none at all (the
|
|
120
|
+
// missing-cache-key throw, and every failure of the packed-shard stream it
|
|
121
|
+
// delegates to — including the Rust-reported `failed` status and the 60 s
|
|
122
|
+
// stall guard — reject straight out), and its siblings can still reject from
|
|
123
|
+
// the `init()` / `listen()` calls that precede their try. Treat a rejected
|
|
124
|
+
// stream promise as a stream error so the caller sees the real message.
|
|
125
|
+
//
|
|
126
|
+
// Only while the stream is still running, though. A rejection that arrives
|
|
127
|
+
// AFTER `onComplete`/`onError` has settled the stream is teardown fallout,
|
|
128
|
+
// not the load's outcome: `NativeBridge.processGeometryStreaming` runs its
|
|
129
|
+
// three `unlisten()` calls in a `finally`, which executes after `onComplete`,
|
|
130
|
+
// so a throwing `unlisten` rejects the promise of a load that fully
|
|
131
|
+
// succeeded. Failing it here would discard every mesh already delivered.
|
|
132
|
+
// Post-completion rejections are logged by the `finally` below instead.
|
|
133
|
+
void streamingPromise.catch((error) => {
|
|
134
|
+
if (completed)
|
|
135
|
+
return;
|
|
136
|
+
// `??=` rather than `=`: `onError` sets `streamError` and `completed`
|
|
137
|
+
// together, so the guard above already covers it, but this keeps the
|
|
138
|
+
// "never shadow a richer onError message" property local to the assignment.
|
|
139
|
+
streamError ??= error instanceof Error ? error : new Error(String(error));
|
|
140
|
+
completed = true;
|
|
141
|
+
wake();
|
|
142
|
+
});
|
|
103
143
|
try {
|
|
104
144
|
while (!completed || queuedEvents.length > 0) {
|
|
105
145
|
let drainedEventCount = 0;
|
|
@@ -112,9 +152,7 @@ export async function* streamNativeGeometry(startStream, totalEstimate, coordina
|
|
|
112
152
|
continue;
|
|
113
153
|
}
|
|
114
154
|
queueState.queuedMeshes = Math.max(0, queueState.queuedMeshes - event.meshes.length);
|
|
115
|
-
|
|
116
|
-
// avoid the generic JS RTC/outlier scan on every streamed batch.
|
|
117
|
-
coordinator.processTrustedMeshesIncremental(event.meshes);
|
|
155
|
+
processMeshes(event.meshes);
|
|
118
156
|
totalMeshes += event.meshes.length;
|
|
119
157
|
const coordinateInfo = coordinator.getCurrentCoordinateInfo();
|
|
120
158
|
yield {
|
|
@@ -126,7 +164,7 @@ export async function* streamNativeGeometry(startStream, totalEstimate, coordina
|
|
|
126
164
|
};
|
|
127
165
|
drainedEventCount += 1;
|
|
128
166
|
drainedMeshCount += event.meshes.length;
|
|
129
|
-
if (queuedEvents.length > 0) {
|
|
167
|
+
if (coalesce && queuedEvents.length > 0) {
|
|
130
168
|
const shouldYield = drainedEventCount >= MAX_NATIVE_STREAM_EVENTS_PER_TURN ||
|
|
131
169
|
drainedMeshCount >= MAX_NATIVE_STREAM_MESHES_PER_TURN ||
|
|
132
170
|
performance.now() - drainStartedAt >= MAX_NATIVE_STREAM_DRAIN_MS;
|
|
@@ -147,6 +185,14 @@ export async function* streamNativeGeometry(startStream, totalEstimate, coordina
|
|
|
147
185
|
});
|
|
148
186
|
}
|
|
149
187
|
}
|
|
188
|
+
// The in-loop check above only runs while the loop still has a reason to
|
|
189
|
+
// spin. `onError` sets `completed` AND leaves the queue empty, so the wake
|
|
190
|
+
// it triggers falls straight out of the loop past that check — and this
|
|
191
|
+
// generator then reported `complete` for a stream that failed. Re-check on
|
|
192
|
+
// the way out so the error reaches the caller.
|
|
193
|
+
if (streamError) {
|
|
194
|
+
throw streamError;
|
|
195
|
+
}
|
|
150
196
|
}
|
|
151
197
|
finally {
|
|
152
198
|
// Ensure the native stream and its Tauri listeners are torn down
|
|
@@ -155,10 +201,35 @@ export async function* streamNativeGeometry(startStream, totalEstimate, coordina
|
|
|
155
201
|
try {
|
|
156
202
|
await streamingPromise;
|
|
157
203
|
}
|
|
158
|
-
catch {
|
|
159
|
-
|
|
204
|
+
catch (err) {
|
|
205
|
+
// Two ways to land here, neither of which the caller learns anything new
|
|
206
|
+
// from: the rejection arrived while the stream was still running, in which
|
|
207
|
+
// case the handler above already recorded it as `streamError` and the
|
|
208
|
+
// drain loop threw it — this is the same error a second time; or it
|
|
209
|
+
// arrived after the stream had already completed, in which case it is
|
|
210
|
+
// teardown fallout that must NOT retro-fail a finished load. Debug level,
|
|
211
|
+
// because this is the only place that kind is reported at all — a real
|
|
212
|
+
// failure reported through `onError` (rather than only this bare
|
|
213
|
+
// rejection) is not swallowed here: it sets `streamError` unconditionally
|
|
214
|
+
// and the recheck right after this `finally` still throws it below.
|
|
215
|
+
console.debug('[GeometryProcessor] native stream teardown rejected:', err);
|
|
160
216
|
}
|
|
161
217
|
}
|
|
218
|
+
// Defense in depth, matching the shape of the two exit-guard checks above:
|
|
219
|
+
// `onError` is never gated on `completed` — a bridge that reports a genuine
|
|
220
|
+
// failure must win regardless of when that report arrives — so it can still
|
|
221
|
+
// fire after both of those checks already ran clean (streamError was null
|
|
222
|
+
// at both), while this generator sits in the `finally` above awaiting
|
|
223
|
+
// `streamingPromise`. Nothing rechecked `streamError` after that point, so
|
|
224
|
+
// a failure signalled that late was recorded and then never read: the
|
|
225
|
+
// caller got `complete` for a stream that, per its own `onError` call,
|
|
226
|
+
// failed. This does NOT reopen the post-complete teardown case just above —
|
|
227
|
+
// a rejection that only ever reaches the detached `.catch()` (never
|
|
228
|
+
// `onError`) is still gated on `!completed` there and leaves `streamError`
|
|
229
|
+
// null, so that case still falls through to `complete` unchanged.
|
|
230
|
+
if (streamError) {
|
|
231
|
+
throw streamError;
|
|
232
|
+
}
|
|
162
233
|
if (queueState.coalescedBatchCount > 0) {
|
|
163
234
|
console.info(`[GeometryProcessor] Coalesced ${queueState.coalescedBatchCount} native batches while JS drained the queue`);
|
|
164
235
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geometry-native.js","sourceRoot":"","sources":["../src/geometry-native.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAgB/D,+BAA+B;AAE/B,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,8BAA8B,GAAG,KAAK,CAAC;AACpD,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC;AACnD,MAAM,CAAC,MAAM,iCAAiC,GAAG,IAAI,CAAC;AACtD,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAQ7C,gBAAgB;AAEhB,MAAM,UAAU,gBAAgB;IAC9B,MAAM,cAAc,GAAI,UAEtB,CAAC,SAAS,CAAC;IACb,IAAI,OAAO,cAAc,EAAE,KAAK,KAAK,UAAU,EAAE,CAAC;QAChD,OAAO,cAAc,CAAC,KAAK,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,YAA0C,EAC1C,KAAiC,EACjC,UAAiE;IAEjE,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxD,IAAI,SAAS,EAAE,IAAI,KAAK,aAAa,EAAE,CAAC;YACtC,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/C,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC1C,CAAC;YACD,OAAO;QACT,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACxD,MAAM,cAAc,GAClB,SAAS,EAAE,IAAI,KAAK,OAAO;QAC3B,CAAC,YAAY,CAAC,MAAM,IAAI,8BAA8B,IAAI,UAAU,CAAC,YAAY,IAAI,8BAA8B,CAAC,CAAC;IAEvH,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,SAAS,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAClD,UAAU,CAAC,mBAAmB,IAAI,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,UAAU,CAAC,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;AACjD,CAAC;
|
|
1
|
+
{"version":3,"file":"geometry-native.js","sourceRoot":"","sources":["../src/geometry-native.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAgB/D,+BAA+B;AAE/B,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,8BAA8B,GAAG,KAAK,CAAC;AACpD,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC;AACnD,MAAM,CAAC,MAAM,iCAAiC,GAAG,IAAI,CAAC;AACtD,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAQ7C,gBAAgB;AAEhB,MAAM,UAAU,gBAAgB;IAC9B,MAAM,cAAc,GAAI,UAEtB,CAAC,SAAS,CAAC;IACb,IAAI,OAAO,cAAc,EAAE,KAAK,KAAK,UAAU,EAAE,CAAC;QAChD,OAAO,cAAc,CAAC,KAAK,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,YAA0C,EAC1C,KAAiC,EACjC,UAAiE;IAEjE,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxD,IAAI,SAAS,EAAE,IAAI,KAAK,aAAa,EAAE,CAAC;YACtC,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/C,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC1C,CAAC;YACD,OAAO;QACT,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACxD,MAAM,cAAc,GAClB,SAAS,EAAE,IAAI,KAAK,OAAO;QAC3B,CAAC,YAAY,CAAC,MAAM,IAAI,8BAA8B,IAAI,UAAU,CAAC,YAAY,IAAI,8BAA8B,CAAC,CAAC;IAEvH,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,SAAS,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAClD,UAAU,CAAC,mBAAmB,IAAI,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,UAAU,CAAC,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;AACjD,CAAC;AAyBD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,oBAAoB,CACzC,WAKoC,EACpC,aAAqB,EACrB,WAA8B,EAC9B,kBAA0D,EAC1D,UAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,KAAK,CAAC;IAC5C,MAAM,aAAa,GACjB,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC,MAAkB,EAAE,EAAE,CAAC,WAAW,CAAC,+BAA+B,CAAC,MAAM,CAAC,CAAC,CAAC;IAEzG,WAAW,CAAC,KAAK,EAAE,CAAC;IAEpB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IACvC,MAAM,gBAAgB,EAAE,CAAC;IACzB,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAEzC,MAAM,YAAY,GAAiC,EAAE,CAAC;IACtD,MAAM,UAAU,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,CAAC;IAC/D,IAAI,cAAc,GAAwB,IAAI,CAAC;IAC/C,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,WAAW,GAAiB,IAAI,CAAC;IACrC,IAAI,oBAAwC,CAAC;IAC7C,IAAI,oBAAqD,CAAC;IAC1D,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,cAAc,EAAE,CAAC;YACnB,cAAc,EAAE,CAAC;YACjB,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,KAAiC,EAAE,EAAE;QACpD,IAAI,QAAQ,EAAE,CAAC;YACb,2BAA2B,CAAC,YAAY,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,WAAW,CAAC;QACnC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC;YACzF,IAAI,EAAE,CAAC;QACT,CAAC;QACD,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE;YACzB,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC5D,IAAI,EAAE,CAAC;QACT,CAAC;QACD,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;YACpB,kBAAkB,CAAC,KAAK,CAAC,CAAC;YAC1B,oBAAoB,GAAG,KAAK,CAAC,WAAW,CAAC;YACzC,oBAAoB,GAAG,KAAK,CAAC,WAAW,CAAC;YACzC,SAAS,GAAG,IAAI,CAAC;YACjB,IAAI,EAAE,CAAC;QACT,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,WAAW,GAAG,KAAK,CAAC;YACpB,SAAS,GAAG,IAAI,CAAC;YACjB,IAAI,EAAE,CAAC;QACT,CAAC;KACF,CAAC,CAAC;IAEH,6EAA6E;IAC7E,0EAA0E;IAC1E,8EAA8E;IAC9E,4EAA4E;IAC5E,8EAA8E;IAC9E,8EAA8E;IAC9E,2EAA2E;IAC3E,0EAA0E;IAC1E,6EAA6E;IAC7E,2EAA2E;IAC3E,wEAAwE;IACxE,EAAE;IACF,2EAA2E;IAC3E,2EAA2E;IAC3E,2EAA2E;IAC3E,8EAA8E;IAC9E,oEAAoE;IACpE,yEAAyE;IACzE,wEAAwE;IACxE,KAAK,gBAAgB,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAC7C,IAAI,SAAS;YAAE,OAAO;QACtB,sEAAsE;QACtE,qEAAqE;QACrE,4EAA4E;QAC5E,WAAW,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1E,SAAS,GAAG,IAAI,CAAC;QACjB,IAAI,EAAE,CAAC;IACT,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,CAAC,SAAS,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,IAAI,iBAAiB,GAAG,CAAC,CAAC;YAC1B,IAAI,gBAAgB,GAAG,CAAC,CAAC;YACzB,IAAI,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YACvC,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,EAAG,CAAC;gBACpC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;oBACjC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;oBACtD,SAAS;gBACX,CAAC;gBAED,UAAU,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACrF,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC5B,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;gBACnC,MAAM,cAAc,GAAG,WAAW,CAAC,wBAAwB,EAAE,CAAC;gBAC9D,MAAM;oBACJ,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,UAAU,EAAE,WAAW;oBACvB,cAAc,EAAE,cAAc,IAAI,SAAS;oBAC3C,eAAe,EAAE,KAAK,CAAC,eAAe;iBACvC,CAAC;gBACF,iBAAiB,IAAI,CAAC,CAAC;gBACvB,gBAAgB,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;gBAExC,IAAI,QAAQ,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACxC,MAAM,WAAW,GACf,iBAAiB,IAAI,iCAAiC;wBACtD,gBAAgB,IAAI,iCAAiC;wBACrD,WAAW,CAAC,GAAG,EAAE,GAAG,cAAc,IAAI,0BAA0B,CAAC;oBACnE,IAAI,WAAW,EAAE,CAAC;wBAChB,MAAM,gBAAgB,EAAE,CAAC;wBACzB,iBAAiB,GAAG,CAAC,CAAC;wBACtB,gBAAgB,GAAG,CAAC,CAAC;wBACrB,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;oBACrC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,WAAW,CAAC;YACpB,CAAC;YAED,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBAClC,cAAc,GAAG,OAAO,CAAC;gBAC3B,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,yEAAyE;QACzE,2EAA2E;QAC3E,wEAAwE;QACxE,2EAA2E;QAC3E,+CAA+C;QAC/C,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,WAAW,CAAC;QACpB,CAAC;IACH,CAAC;YAAS,CAAC;QACT,iEAAiE;QACjE,sEAAsE;QACtE,4DAA4D;QAC5D,IAAI,CAAC;YACH,MAAM,gBAAgB,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,yEAAyE;YACzE,2EAA2E;YAC3E,sEAAsE;YACtE,oEAAoE;YACpE,sEAAsE;YACtE,0EAA0E;YAC1E,uEAAuE;YACvE,iEAAiE;YACjE,0EAA0E;YAC1E,oEAAoE;YACpE,OAAO,CAAC,KAAK,CAAC,sDAAsD,EAAE,GAAG,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,4EAA4E;IAC5E,4EAA4E;IAC5E,0EAA0E;IAC1E,sEAAsE;IACtE,2EAA2E;IAC3E,sEAAsE;IACtE,uEAAuE;IACvE,4EAA4E;IAC5E,oEAAoE;IACpE,2EAA2E;IAC3E,kEAAkE;IAClE,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,WAAW,CAAC;IACpB,CAAC;IAED,IAAI,UAAU,CAAC,mBAAmB,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CACV,iCAAiC,UAAU,CAAC,mBAAmB,4CAA4C,CAC5G,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,WAAW,CAAC,sBAAsB,EAAE,CAAC;IAC5D,MAAM;QACJ,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,oBAAoB,IAAI,WAAW;QAChD,cAAc;QACd,2EAA2E;QAC3E,6EAA6E;QAC7E,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAC;AACJ,CAAC"}
|
|
@@ -23,6 +23,40 @@ import type { CoordinateHandler } from './coordinate-handler.js';
|
|
|
23
23
|
import type { TessellationQuality } from './types.js';
|
|
24
24
|
import type { StreamingGeometryEvent } from './index.js';
|
|
25
25
|
import type { BatchSizingConfig } from './batch-sizing.js';
|
|
26
|
+
/**
|
|
27
|
+
* Prepass class-byte layout, mirroring the `PREPASS_CLASS_*` definitions in
|
|
28
|
+
* `rust/processing/src/shard_classes.rs` (the source of truth — these are
|
|
29
|
+
* pinned to it by `prepass-class-spans.test.ts`).
|
|
30
|
+
*
|
|
31
|
+
* The producer packs a named code in the LOW bits and composes FLAG bits on
|
|
32
|
+
* top (`PREPASS_CLASS_FLAG_GEOMETRY_JOB` 0x80, `..._FLAG_TYPE_CANDIDATE`
|
|
33
|
+
* 0x40), so a consumer must mask before comparing — the Rust consumer does
|
|
34
|
+
* (`gpu_meshes/prepass_discovery.rs`), and so does {@link extractPrepassSpanLists}.
|
|
35
|
+
*/
|
|
36
|
+
export declare const PREPASS_CLASS_CODE_MASK = 63;
|
|
37
|
+
/** `IFCSTYLEDITEM`. */
|
|
38
|
+
export declare const PREPASS_CLASS_STYLED_ITEM = 4;
|
|
39
|
+
/** `IFCINDEXEDCOLOURMAP`. */
|
|
40
|
+
export declare const PREPASS_CLASS_INDEXED_COLOUR_MAP = 5;
|
|
41
|
+
/** `IFCMATERIALDEFINITIONREPRESENTATION`. */
|
|
42
|
+
export declare const PREPASS_CLASS_MATERIAL_DEF_REPR = 6;
|
|
43
|
+
/** `IFCRELASSOCIATESMATERIAL`. */
|
|
44
|
+
export declare const PREPASS_CLASS_REL_ASSOCIATES_MATERIAL = 7;
|
|
45
|
+
/** `IFCRELVOIDSELEMENT`. */
|
|
46
|
+
export declare const PREPASS_CLASS_REL_VOIDS = 8;
|
|
47
|
+
/** `IFCRELFILLSELEMENT`. */
|
|
48
|
+
export declare const PREPASS_CLASS_REL_FILLS = 9;
|
|
49
|
+
/** `IFCRELAGGREGATES`. */
|
|
50
|
+
export declare const PREPASS_CLASS_REL_AGGREGATES = 10;
|
|
51
|
+
/**
|
|
52
|
+
* Build one `(id, start, length)` span list per host-consumed prepass class
|
|
53
|
+
* from the stitched shard columns, in FILE ORDER. Every comparison goes
|
|
54
|
+
* through {@link PREPASS_CLASS_CODE_MASK}, so a record that carries a flag bit
|
|
55
|
+
* alongside its named code still lands in its list instead of being dropped.
|
|
56
|
+
* Returns exact-size arrays (one entry per class in `HOST_SPAN_CLASSES`,
|
|
57
|
+
* empty when the file has none).
|
|
58
|
+
*/
|
|
59
|
+
export declare function extractPrepassSpanLists(classes: Uint8Array, ids: Uint32Array, starts: Uint32Array, lengths: Uint32Array): Map<number, Uint32Array>;
|
|
26
60
|
/**
|
|
27
61
|
* Plan content-affinity routing for one chunk: assign each job (by index) to a
|
|
28
62
|
* worker bucket so that every job sharing an affinity key lands on the SAME
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geometry-parallel.d.ts","sourceRoot":"","sources":["../src/geometry-parallel.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAY,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAO3D;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,WAAW,EAAE,MAAM,GAClB;IAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAc7C;
|
|
1
|
+
{"version":3,"file":"geometry-parallel.d.ts","sourceRoot":"","sources":["../src/geometry-parallel.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAY,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAO3D;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,KAAO,CAAC;AAC5C,uBAAuB;AACvB,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,6BAA6B;AAC7B,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAClD,6CAA6C;AAC7C,eAAO,MAAM,+BAA+B,IAAI,CAAC;AACjD,kCAAkC;AAClC,eAAO,MAAM,qCAAqC,IAAI,CAAC;AACvD,4BAA4B;AAC5B,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,4BAA4B;AAC5B,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,0BAA0B;AAC1B,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAa/C;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,UAAU,EACnB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,WAAW,GACnB,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAmB1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,WAAW,EAAE,MAAM,GAClB;IAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAc7C;AAiKD,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CACd,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,WAAW,KACjB,IAAI,CAAC;IACV;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACjD;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACzC;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5E;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAuB,eAAe,CACpC,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,iBAAiB,EAC9B,eAAe,CAAC,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE;AACrD,gFAAgF;AAChF,WAAW,CAAC,EAAE,iBAAiB,EAC/B,OAAO,CAAC,EAAE,sBAAsB,GAC/B,cAAc,CAAC,sBAAsB,CAAC,CAkwCxC"}
|
|
@@ -8,6 +8,73 @@ import { notifyIfWasmAssetUnavailable, notifyIfWorkerScriptUnavailable } from '.
|
|
|
8
8
|
// `IfcLiteBridge.init()` path can reuse whatever this pool already compiled
|
|
9
9
|
// (and vice versa) instead of fetching the same binary a second time.
|
|
10
10
|
import { compileSharedWasmModule } from './wasm-shared-module.js';
|
|
11
|
+
/**
|
|
12
|
+
* Prepass class-byte layout, mirroring the `PREPASS_CLASS_*` definitions in
|
|
13
|
+
* `rust/processing/src/shard_classes.rs` (the source of truth — these are
|
|
14
|
+
* pinned to it by `prepass-class-spans.test.ts`).
|
|
15
|
+
*
|
|
16
|
+
* The producer packs a named code in the LOW bits and composes FLAG bits on
|
|
17
|
+
* top (`PREPASS_CLASS_FLAG_GEOMETRY_JOB` 0x80, `..._FLAG_TYPE_CANDIDATE`
|
|
18
|
+
* 0x40), so a consumer must mask before comparing — the Rust consumer does
|
|
19
|
+
* (`gpu_meshes/prepass_discovery.rs`), and so does {@link extractPrepassSpanLists}.
|
|
20
|
+
*/
|
|
21
|
+
export const PREPASS_CLASS_CODE_MASK = 0x3f;
|
|
22
|
+
/** `IFCSTYLEDITEM`. */
|
|
23
|
+
export const PREPASS_CLASS_STYLED_ITEM = 4;
|
|
24
|
+
/** `IFCINDEXEDCOLOURMAP`. */
|
|
25
|
+
export const PREPASS_CLASS_INDEXED_COLOUR_MAP = 5;
|
|
26
|
+
/** `IFCMATERIALDEFINITIONREPRESENTATION`. */
|
|
27
|
+
export const PREPASS_CLASS_MATERIAL_DEF_REPR = 6;
|
|
28
|
+
/** `IFCRELASSOCIATESMATERIAL`. */
|
|
29
|
+
export const PREPASS_CLASS_REL_ASSOCIATES_MATERIAL = 7;
|
|
30
|
+
/** `IFCRELVOIDSELEMENT`. */
|
|
31
|
+
export const PREPASS_CLASS_REL_VOIDS = 8;
|
|
32
|
+
/** `IFCRELFILLSELEMENT`. */
|
|
33
|
+
export const PREPASS_CLASS_REL_FILLS = 9;
|
|
34
|
+
/** `IFCRELAGGREGATES`. */
|
|
35
|
+
export const PREPASS_CLASS_REL_AGGREGATES = 10;
|
|
36
|
+
/** The classes the host builds span lists for (every other code is ignored). */
|
|
37
|
+
const HOST_SPAN_CLASSES = [
|
|
38
|
+
PREPASS_CLASS_STYLED_ITEM,
|
|
39
|
+
PREPASS_CLASS_INDEXED_COLOUR_MAP,
|
|
40
|
+
PREPASS_CLASS_MATERIAL_DEF_REPR,
|
|
41
|
+
PREPASS_CLASS_REL_ASSOCIATES_MATERIAL,
|
|
42
|
+
PREPASS_CLASS_REL_VOIDS,
|
|
43
|
+
PREPASS_CLASS_REL_FILLS,
|
|
44
|
+
PREPASS_CLASS_REL_AGGREGATES,
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* Build one `(id, start, length)` span list per host-consumed prepass class
|
|
48
|
+
* from the stitched shard columns, in FILE ORDER. Every comparison goes
|
|
49
|
+
* through {@link PREPASS_CLASS_CODE_MASK}, so a record that carries a flag bit
|
|
50
|
+
* alongside its named code still lands in its list instead of being dropped.
|
|
51
|
+
* Returns exact-size arrays (one entry per class in `HOST_SPAN_CLASSES`,
|
|
52
|
+
* empty when the file has none).
|
|
53
|
+
*/
|
|
54
|
+
export function extractPrepassSpanLists(classes, ids, starts, lengths) {
|
|
55
|
+
// Sized by the code mask rather than by the highest class the host consumes:
|
|
56
|
+
// a masked code is always < 64, so a class added on the Rust side cannot
|
|
57
|
+
// write out of bounds here (typed arrays discard such writes silently).
|
|
58
|
+
const counts = new Uint32Array(PREPASS_CLASS_CODE_MASK + 1);
|
|
59
|
+
for (let i = 0; i < classes.length; i++)
|
|
60
|
+
counts[classes[i] & PREPASS_CLASS_CODE_MASK]++;
|
|
61
|
+
const slots = new Map();
|
|
62
|
+
for (const k of HOST_SPAN_CLASSES)
|
|
63
|
+
slots.set(k, { arr: new Uint32Array(counts[k] * 3), w: 0 });
|
|
64
|
+
for (let i = 0; i < classes.length; i++) {
|
|
65
|
+
const slot = slots.get(classes[i] & PREPASS_CLASS_CODE_MASK);
|
|
66
|
+
if (!slot)
|
|
67
|
+
continue;
|
|
68
|
+
slot.arr[slot.w] = ids[i];
|
|
69
|
+
slot.arr[slot.w + 1] = starts[i];
|
|
70
|
+
slot.arr[slot.w + 2] = lengths[i];
|
|
71
|
+
slot.w += 3;
|
|
72
|
+
}
|
|
73
|
+
const spans = new Map();
|
|
74
|
+
for (const [k, slot] of slots)
|
|
75
|
+
spans.set(k, slot.arr);
|
|
76
|
+
return spans;
|
|
77
|
+
}
|
|
11
78
|
/**
|
|
12
79
|
* Plan content-affinity routing for one chunk: assign each job (by index) to a
|
|
13
80
|
* worker bucket so that every job sharing an affinity key lands on the SAME
|
|
@@ -70,6 +137,26 @@ function readShardScanFlag() {
|
|
|
70
137
|
return false;
|
|
71
138
|
return true;
|
|
72
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Terminate a pool worker on a teardown path that is already unwinding.
|
|
142
|
+
*
|
|
143
|
+
* `Worker.terminate()` is specified never to throw, and is a no-op on a worker
|
|
144
|
+
* that is already gone — so every one of these teardown calls is expected to
|
|
145
|
+
* succeed and a throw means something unexpected about the host, not a
|
|
146
|
+
* double-terminate. Worth one line; never worth failing a teardown that runs
|
|
147
|
+
* while a real error is on its way to the caller.
|
|
148
|
+
*
|
|
149
|
+
* Bounded by construction: each caller terminates the pool once and then
|
|
150
|
+
* throws, returns, or leaves the generator.
|
|
151
|
+
*/
|
|
152
|
+
function terminateWorkerQuietly(worker, label) {
|
|
153
|
+
try {
|
|
154
|
+
worker.terminate();
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
console.warn(`[stream] ${label} terminate failed:`, err);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
73
160
|
/**
|
|
74
161
|
* SPIKE: stitch N speculative shard scans into the full entity index —
|
|
75
162
|
* byte-identical to the single-threaded scan. Port of the native
|
|
@@ -354,6 +441,13 @@ existingSab, options) {
|
|
|
354
441
|
// (no flat mesh carries them). Forward straight through to the consumer.
|
|
355
442
|
const instancedGeometryHashIds = msg.instancedGeometryHashIds;
|
|
356
443
|
const instancedGeometryHashValues = msg.instancedGeometryHashValues;
|
|
444
|
+
// #1891: the world boxes for those same ids, six values per id. Travels
|
|
445
|
+
// with the ids, never on its own — an aabb array without its id array
|
|
446
|
+
// indexes nothing.
|
|
447
|
+
const instancedGeometryAabbValues = msg.instancedGeometryAabbValues;
|
|
448
|
+
// #1993: and their proved volumes, one per id. Same rule as the boxes —
|
|
449
|
+
// it travels with the ids or not at all.
|
|
450
|
+
const instancedGeometryVolumeValues = msg.instancedGeometryVolumeValues;
|
|
357
451
|
if (meshes.length > 0 ||
|
|
358
452
|
(instancedShards && instancedShards.length > 0) ||
|
|
359
453
|
(instancedGeometryHashIds && instancedGeometryHashIds.length > 0)) {
|
|
@@ -376,7 +470,12 @@ existingSab, options) {
|
|
|
376
470
|
coordinateInfo: coordinateInfo || undefined,
|
|
377
471
|
...(instancedShards && instancedShards.length > 0 ? { instancedShards } : {}),
|
|
378
472
|
...(instancedGeometryHashIds && instancedGeometryHashIds.length > 0
|
|
379
|
-
? {
|
|
473
|
+
? {
|
|
474
|
+
instancedGeometryHashIds,
|
|
475
|
+
instancedGeometryHashValues,
|
|
476
|
+
...(instancedGeometryAabbValues ? { instancedGeometryAabbValues } : {}),
|
|
477
|
+
...(instancedGeometryVolumeValues ? { instancedGeometryVolumeValues } : {}),
|
|
478
|
+
}
|
|
380
479
|
: {}),
|
|
381
480
|
});
|
|
382
481
|
wake();
|
|
@@ -519,7 +618,23 @@ existingSab, options) {
|
|
|
519
618
|
try {
|
|
520
619
|
w.postMessage({ type: 'stream-end' });
|
|
521
620
|
}
|
|
522
|
-
catch {
|
|
621
|
+
catch (err) {
|
|
622
|
+
// A structured-clonable payload posted to a terminated worker is a
|
|
623
|
+
// no-op, not a throw — so this means the port is in a state we did
|
|
624
|
+
// not expect. That worker will never flush its tail: `complete` is
|
|
625
|
+
// posted ONLY from `emitSessionEnd` in geometry.worker.js, which
|
|
626
|
+
// fires ONLY in response to `stream-end`. The drain loop below waits
|
|
627
|
+
// for a `complete` from every worker (`workersCompleted >=
|
|
628
|
+
// workers.length`), so leaving this as a log would make the load
|
|
629
|
+
// hang forever instead of failing loudly — the same "swallowed
|
|
630
|
+
// failure" shape as the fixes already on this branch, just a stall
|
|
631
|
+
// instead of a false success. Surface it as a load error and
|
|
632
|
+
// terminate the unreachable worker so it isn't left dangling.
|
|
633
|
+
console.warn('[stream] stream-end postMessage failed; failing the load instead of hanging on that worker:', err);
|
|
634
|
+
workerError = workerError ?? new Error(`Geometry worker failed: stream-end could not be delivered (${err instanceof Error ? err.message : String(err)})`);
|
|
635
|
+
terminateWorkerQuietly(w, 'process worker');
|
|
636
|
+
wake();
|
|
637
|
+
}
|
|
523
638
|
}
|
|
524
639
|
};
|
|
525
640
|
const sendStreamStartIfReady = () => {
|
|
@@ -777,35 +892,17 @@ existingSab, options) {
|
|
|
777
892
|
// stitched columns, split into one contiguous slice per worker, and
|
|
778
893
|
// resolve them in parallel while everyone waits on the pre-pass scan.
|
|
779
894
|
const classes = stitched.classes;
|
|
780
|
-
|
|
781
|
-
// 6 material def repr, 7 rel-associates-material, 8 voids, 9 fills,
|
|
782
|
-
// 10 aggregates. Extract each list in FILE ORDER.
|
|
783
|
-
const counts = new Uint32Array(11);
|
|
784
|
-
for (let i = 0; i < classes.length; i++)
|
|
785
|
-
counts[classes[i]]++;
|
|
786
|
-
const kinds = [4, 5, 6, 7, 8, 9, 10];
|
|
787
|
-
const spanLists = new Map();
|
|
788
|
-
for (const k of kinds)
|
|
789
|
-
spanLists.set(k, { arr: new Uint32Array(counts[k] * 3), w: 0 });
|
|
790
|
-
for (let i = 0; i < classes.length; i++) {
|
|
791
|
-
const slot = spanLists.get(classes[i]);
|
|
792
|
-
if (!slot)
|
|
793
|
-
continue;
|
|
794
|
-
slot.arr[slot.w] = ids[i];
|
|
795
|
-
slot.arr[slot.w + 1] = starts[i];
|
|
796
|
-
slot.arr[slot.w + 2] = lengths[i];
|
|
797
|
-
slot.w += 3;
|
|
798
|
-
}
|
|
895
|
+
const spanLists = extractPrepassSpanLists(classes, ids, starts, lengths);
|
|
799
896
|
supportSpans = {
|
|
800
|
-
colourMapSpans: spanLists.get(
|
|
801
|
-
materialDefSpans: spanLists.get(
|
|
802
|
-
relMaterialSpans: spanLists.get(
|
|
803
|
-
voidSpans: spanLists.get(
|
|
804
|
-
fillsSpans: spanLists.get(
|
|
805
|
-
aggregateSpans: spanLists.get(
|
|
897
|
+
colourMapSpans: spanLists.get(PREPASS_CLASS_INDEXED_COLOUR_MAP),
|
|
898
|
+
materialDefSpans: spanLists.get(PREPASS_CLASS_MATERIAL_DEF_REPR),
|
|
899
|
+
relMaterialSpans: spanLists.get(PREPASS_CLASS_REL_ASSOCIATES_MATERIAL),
|
|
900
|
+
voidSpans: spanLists.get(PREPASS_CLASS_REL_VOIDS),
|
|
901
|
+
fillsSpans: spanLists.get(PREPASS_CLASS_REL_FILLS),
|
|
902
|
+
aggregateSpans: spanLists.get(PREPASS_CLASS_REL_AGGREGATES),
|
|
806
903
|
};
|
|
807
|
-
const
|
|
808
|
-
const
|
|
904
|
+
const styledSpans = spanLists.get(PREPASS_CLASS_STYLED_ITEM);
|
|
905
|
+
const styledCount = styledSpans.length / 3;
|
|
809
906
|
// 2 slices per worker (round-robin): the tail is set by the SLOWEST
|
|
810
907
|
// worker, and macOS occasionally schedules one onto a slow core — halving
|
|
811
908
|
// the slice size halves the damage a slow core can do to the tail.
|
|
@@ -1276,23 +1373,14 @@ existingSab, options) {
|
|
|
1276
1373
|
}
|
|
1277
1374
|
if (workerError) {
|
|
1278
1375
|
for (const w of workers) {
|
|
1279
|
-
|
|
1280
|
-
w.terminate();
|
|
1281
|
-
}
|
|
1282
|
-
catch { /* cleanup — safe to ignore */ }
|
|
1283
|
-
}
|
|
1284
|
-
try {
|
|
1285
|
-
prepassWorker.terminate();
|
|
1376
|
+
terminateWorkerQuietly(w, 'process worker');
|
|
1286
1377
|
}
|
|
1287
|
-
|
|
1378
|
+
terminateWorkerQuietly(prepassWorker, 'pre-pass worker');
|
|
1288
1379
|
throw workerError;
|
|
1289
1380
|
}
|
|
1290
1381
|
if (prepassError) {
|
|
1291
1382
|
for (const w of workers) {
|
|
1292
|
-
|
|
1293
|
-
w.terminate();
|
|
1294
|
-
}
|
|
1295
|
-
catch { /* cleanup — safe to ignore */ }
|
|
1383
|
+
terminateWorkerQuietly(w, 'process worker');
|
|
1296
1384
|
}
|
|
1297
1385
|
throw prepassError;
|
|
1298
1386
|
}
|
|
@@ -1303,10 +1391,7 @@ existingSab, options) {
|
|
|
1303
1391
|
// explicit terminate to exit.
|
|
1304
1392
|
if (prepassDone && !streamStartSentToWorkers && prepassJobsTotal === 0) {
|
|
1305
1393
|
for (const w of workers) {
|
|
1306
|
-
|
|
1307
|
-
w.terminate();
|
|
1308
|
-
}
|
|
1309
|
-
catch { /* cleanup — safe to ignore */ }
|
|
1394
|
+
terminateWorkerQuietly(w, 'process worker');
|
|
1310
1395
|
}
|
|
1311
1396
|
const coordinateInfo = coordinator.getFinalCoordinateInfo();
|
|
1312
1397
|
yield { type: 'complete', totalMeshes: 0, coordinateInfo };
|
|
@@ -1341,15 +1426,9 @@ existingSab, options) {
|
|
|
1341
1426
|
}
|
|
1342
1427
|
finally {
|
|
1343
1428
|
for (const w of workers) {
|
|
1344
|
-
|
|
1345
|
-
w.terminate();
|
|
1346
|
-
}
|
|
1347
|
-
catch { /* cleanup — safe to ignore */ }
|
|
1348
|
-
}
|
|
1349
|
-
try {
|
|
1350
|
-
prepassWorker.terminate();
|
|
1429
|
+
terminateWorkerQuietly(w, 'process worker');
|
|
1351
1430
|
}
|
|
1352
|
-
|
|
1431
|
+
terminateWorkerQuietly(prepassWorker, 'pre-pass worker');
|
|
1353
1432
|
}
|
|
1354
1433
|
}
|
|
1355
1434
|
//# sourceMappingURL=geometry-parallel.js.map
|