@react-three/tsl 10.0.0-canary.5140ac8 → 10.0.0-canary.58acabc
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/index.cjs +221 -95
- package/dist/index.d.cts +307 -66
- package/dist/index.d.mts +307 -66
- package/dist/index.d.ts +307 -66
- package/dist/index.mjs +222 -96
- package/package.json +2 -2
- package/readme.md +3 -3
package/dist/index.cjs
CHANGED
|
@@ -73,6 +73,13 @@ function withStagedOverlay(store, kind, committed) {
|
|
|
73
73
|
}
|
|
74
74
|
return view;
|
|
75
75
|
}
|
|
76
|
+
function readWithStaged(store, kind, committed, scope, isLeaf) {
|
|
77
|
+
if (scope === void 0) return withStagedOverlay(store, kind, committed);
|
|
78
|
+
const scopeData = committed[scope];
|
|
79
|
+
const current = scopeData && typeof scopeData === "object" && !isLeaf(scopeData) ? scopeData : {};
|
|
80
|
+
const staged = scope === ROOT_SCOPE ? void 0 : peekStaged(store, kind, scope);
|
|
81
|
+
return staged ? { ...current, ...staged } : current;
|
|
82
|
+
}
|
|
76
83
|
function flushStagedScope(store, kind, scopeKey, isLeaf) {
|
|
77
84
|
const registry = getKindRegistry(store, kind);
|
|
78
85
|
const staged = registry.staged.get(scopeKey);
|
|
@@ -271,6 +278,103 @@ function configureTSL(next) {
|
|
|
271
278
|
for (const store of primaries) applyConfig(store, config);
|
|
272
279
|
}
|
|
273
280
|
|
|
281
|
+
const owners = /* @__PURE__ */ new WeakMap();
|
|
282
|
+
const warned$1 = /* @__PURE__ */ new WeakSet();
|
|
283
|
+
const sweeps = /* @__PURE__ */ new WeakMap();
|
|
284
|
+
function createOwner(store, rebuild) {
|
|
285
|
+
return { store, pipeline: null, scenePass: null, passes: {}, mounted: false, releaseTimer: null, rebuild };
|
|
286
|
+
}
|
|
287
|
+
function disposeOwnerResources(owner) {
|
|
288
|
+
owner.scenePass?.node.dispose();
|
|
289
|
+
owner.pipeline?.dispose();
|
|
290
|
+
owner.scenePass = null;
|
|
291
|
+
owner.pipeline = null;
|
|
292
|
+
owner.passes = {};
|
|
293
|
+
}
|
|
294
|
+
function activeOwner(store) {
|
|
295
|
+
return owners.get(store)?.at(-1);
|
|
296
|
+
}
|
|
297
|
+
function renderThroughPipeline(store) {
|
|
298
|
+
return () => {
|
|
299
|
+
const pipeline = store.getState().renderPipeline;
|
|
300
|
+
if (pipeline?.render) pipeline.render();
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function claimOwnership(owner) {
|
|
304
|
+
if (owner.releaseTimer !== null) clearTimeout(owner.releaseTimer);
|
|
305
|
+
owner.releaseTimer = null;
|
|
306
|
+
owner.mounted = true;
|
|
307
|
+
let list = owners.get(owner.store);
|
|
308
|
+
if (!list) owners.set(owner.store, list = []);
|
|
309
|
+
if (list.includes(owner)) return;
|
|
310
|
+
if (list.some((other) => other.mounted) && !warned$1.has(owner.store)) {
|
|
311
|
+
warned$1.add(owner.store);
|
|
312
|
+
if (typeof process === "undefined" || process.env.NODE_ENV !== "production") {
|
|
313
|
+
console.warn(
|
|
314
|
+
"[useRenderPipeline] More than one mounted component configures this canvas's render pipeline. The most recently mounted one renders; the others take over again when it unmounts."
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
list.push(owner);
|
|
319
|
+
scheduleSweep(owner.store);
|
|
320
|
+
}
|
|
321
|
+
function scheduleSweep(store) {
|
|
322
|
+
if (sweeps.has(store)) return;
|
|
323
|
+
sweeps.set(
|
|
324
|
+
store,
|
|
325
|
+
setTimeout(() => {
|
|
326
|
+
sweeps.delete(store);
|
|
327
|
+
const active = activeOwner(store);
|
|
328
|
+
for (const owner of [...owners.get(store) ?? []]) {
|
|
329
|
+
if (owner !== active && !owner.mounted && owner.releaseTimer === null) releaseOwner(owner);
|
|
330
|
+
}
|
|
331
|
+
})
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
function publishOwner(owner) {
|
|
335
|
+
if (activeOwner(owner.store) !== owner || !owner.pipeline) return;
|
|
336
|
+
owner.store.setState({ renderPipeline: owner.pipeline, passes: owner.passes });
|
|
337
|
+
extension.setRenderOverride(owner.store, renderThroughPipeline(owner.store));
|
|
338
|
+
}
|
|
339
|
+
function scheduleRelease(owner) {
|
|
340
|
+
owner.mounted = false;
|
|
341
|
+
if (owner.releaseTimer !== null) return;
|
|
342
|
+
owner.releaseTimer = setTimeout(() => releaseOwner(owner));
|
|
343
|
+
}
|
|
344
|
+
function releaseOwner(owner) {
|
|
345
|
+
if (owner.releaseTimer !== null) clearTimeout(owner.releaseTimer);
|
|
346
|
+
owner.releaseTimer = null;
|
|
347
|
+
const { store } = owner;
|
|
348
|
+
const list = owners.get(store);
|
|
349
|
+
const index = list?.indexOf(owner) ?? -1;
|
|
350
|
+
if (list && index !== -1) {
|
|
351
|
+
const wasActive = index === list.length - 1;
|
|
352
|
+
list.splice(index, 1);
|
|
353
|
+
if (wasActive) {
|
|
354
|
+
const next = activeOwner(store);
|
|
355
|
+
if (next) {
|
|
356
|
+
publishOwner(next);
|
|
357
|
+
} else {
|
|
358
|
+
store.setState({ renderPipeline: null, passes: {} });
|
|
359
|
+
extension.setRenderOverride(store, null);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
disposeOwnerResources(owner);
|
|
364
|
+
}
|
|
365
|
+
function releaseAllOwners(store) {
|
|
366
|
+
clearTimeout(sweeps.get(store));
|
|
367
|
+
sweeps.delete(store);
|
|
368
|
+
const list = owners.get(store);
|
|
369
|
+
if (!list) return;
|
|
370
|
+
owners.delete(store);
|
|
371
|
+
for (const owner of list) {
|
|
372
|
+
if (owner.releaseTimer !== null) clearTimeout(owner.releaseTimer);
|
|
373
|
+
owner.releaseTimer = null;
|
|
374
|
+
disposeOwnerResources(owner);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
274
378
|
const SHARED_KEYS = ["uniforms", "nodes", "buffers", "gpuStorage", "_hmrVersion"];
|
|
275
379
|
const following = /* @__PURE__ */ new WeakMap();
|
|
276
380
|
function createResourceState() {
|
|
@@ -299,6 +403,7 @@ function followPrimary(store, primary) {
|
|
|
299
403
|
following.set(store, primary.subscribe(sync));
|
|
300
404
|
}
|
|
301
405
|
function dispose(store) {
|
|
406
|
+
releaseAllOwners(store);
|
|
302
407
|
untrackPrimary(store);
|
|
303
408
|
following.get(store)?.();
|
|
304
409
|
following.delete(store);
|
|
@@ -704,8 +809,9 @@ function useUniforms(creatorOrScope, scope) {
|
|
|
704
809
|
input: memoizedInput,
|
|
705
810
|
create: () => {
|
|
706
811
|
if (isReader) return {};
|
|
707
|
-
if (typeof processedInput.candidates !== "object" || processedInput.candidates === null)
|
|
812
|
+
if (typeof processedInput.candidates !== "object" || processedInput.candidates === null) {
|
|
708
813
|
throw new Error("Invalid uniform input");
|
|
814
|
+
}
|
|
709
815
|
return processedInput.candidates;
|
|
710
816
|
},
|
|
711
817
|
prepare: (name, candidate) => createUniform(name, candidate, scope),
|
|
@@ -723,13 +829,7 @@ function useUniforms(creatorOrScope, scope) {
|
|
|
723
829
|
if (!equals) existing.value = newVal;
|
|
724
830
|
}
|
|
725
831
|
});
|
|
726
|
-
|
|
727
|
-
if (memoizedInput === void 0) {
|
|
728
|
-
uniforms = storeUniforms;
|
|
729
|
-
} else if (typeof memoizedInput === "string") {
|
|
730
|
-
const scopeData = storeUniforms[memoizedInput];
|
|
731
|
-
uniforms = scopeData && !isUniformNode(scopeData) ? scopeData : {};
|
|
732
|
-
}
|
|
832
|
+
const uniforms = isReader ? readWithStaged(store, "uniforms", storeUniforms, memoizedInput, isUniformNode) : created;
|
|
733
833
|
return { ...uniforms, removeUniforms, clearUniforms, rebuildUniforms };
|
|
734
834
|
}
|
|
735
835
|
function rebuildAllUniforms(store, scope) {
|
|
@@ -846,13 +946,7 @@ function useNodes(creatorOrScope, scope) {
|
|
|
846
946
|
return node;
|
|
847
947
|
}
|
|
848
948
|
});
|
|
849
|
-
|
|
850
|
-
if (creatorOrScope === void 0) {
|
|
851
|
-
nodes = storeNodes;
|
|
852
|
-
} else if (typeof creatorOrScope === "string") {
|
|
853
|
-
const scopeData = storeNodes[creatorOrScope];
|
|
854
|
-
nodes = scopeData && !isTSLNode(scopeData) ? scopeData : {};
|
|
855
|
-
}
|
|
949
|
+
const nodes = isReader ? readWithStaged(store, "nodes", storeNodes, creatorOrScope, isTSLNode) : created;
|
|
856
950
|
return { ...nodes, removeNodes, clearNodes, rebuildNodes };
|
|
857
951
|
}
|
|
858
952
|
function rebuildAllNodes(store, scope) {
|
|
@@ -1007,13 +1101,7 @@ function useBuffers(creatorOrScope, scope) {
|
|
|
1007
1101
|
return buffer;
|
|
1008
1102
|
}
|
|
1009
1103
|
});
|
|
1010
|
-
|
|
1011
|
-
if (creatorOrScope === void 0) {
|
|
1012
|
-
buffers = storeBuffers;
|
|
1013
|
-
} else if (typeof creatorOrScope === "string") {
|
|
1014
|
-
const scopeData = storeBuffers[creatorOrScope];
|
|
1015
|
-
buffers = scopeData && !isBufferLike(scopeData) ? scopeData : {};
|
|
1016
|
-
}
|
|
1104
|
+
const buffers = isReader ? readWithStaged(store, "buffers", storeBuffers, creatorOrScope, isBufferLike) : created;
|
|
1017
1105
|
return { ...buffers, removeBuffers, clearBuffers, rebuildBuffers, disposeBuffers };
|
|
1018
1106
|
}
|
|
1019
1107
|
function rebuildAllBuffers(store, scope) {
|
|
@@ -1077,13 +1165,7 @@ function useGPUStorage(creatorOrScope, scope) {
|
|
|
1077
1165
|
return storage;
|
|
1078
1166
|
}
|
|
1079
1167
|
});
|
|
1080
|
-
|
|
1081
|
-
if (creatorOrScope === void 0) {
|
|
1082
|
-
gpuStorage = storeStorage;
|
|
1083
|
-
} else if (typeof creatorOrScope === "string") {
|
|
1084
|
-
const scopeData = storeStorage[creatorOrScope];
|
|
1085
|
-
gpuStorage = scopeData && !isStorageLike(scopeData) ? scopeData : {};
|
|
1086
|
-
}
|
|
1168
|
+
const gpuStorage = isReader ? readWithStaged(store, "gpuStorage", storeStorage, creatorOrScope, isStorageLike) : created;
|
|
1087
1169
|
return {
|
|
1088
1170
|
...gpuStorage,
|
|
1089
1171
|
removeStorage,
|
|
@@ -1097,120 +1179,164 @@ function rebuildAllStorage(store, scope) {
|
|
|
1097
1179
|
}
|
|
1098
1180
|
|
|
1099
1181
|
const NO_PASSES = Object.freeze({});
|
|
1100
|
-
function
|
|
1101
|
-
return () => {
|
|
1102
|
-
const pipeline = store.getState().renderPipeline;
|
|
1103
|
-
if (pipeline?.render) pipeline.render();
|
|
1104
|
-
};
|
|
1105
|
-
}
|
|
1106
|
-
function useRenderPipeline(mainCB, setupCB) {
|
|
1182
|
+
function useRenderPipeline(mainCB, setupCB, options) {
|
|
1107
1183
|
const store = extension.useStore();
|
|
1184
|
+
const primary = usePrimaryStore();
|
|
1185
|
+
const view = React.useMemo(() => createResourceView(primary, store), [primary, store]);
|
|
1108
1186
|
const { scene, camera, renderer, isLegacy } = extension.useThree();
|
|
1187
|
+
const hmrVersion = usePrimaryThree((s) => s._hmrVersion);
|
|
1188
|
+
const isOwner = mainCB !== void 0 || setupCB !== void 0;
|
|
1109
1189
|
const callbacksRanRef = React.useRef(false);
|
|
1110
|
-
const scenePassCacheRef = React.useRef(null);
|
|
1111
1190
|
const forceScenePassRebuildRef = React.useRef(false);
|
|
1112
1191
|
const mainCBRef = React.useRef(mainCB);
|
|
1113
1192
|
const setupCBRef = React.useRef(setupCB);
|
|
1193
|
+
const persistRef = React.useRef(options?.persist ?? false);
|
|
1114
1194
|
mainCBRef.current = mainCB;
|
|
1115
1195
|
setupCBRef.current = setupCB;
|
|
1196
|
+
persistRef.current = options?.persist ?? false;
|
|
1116
1197
|
const [rebuildVersion, setRebuildVersion] = React.useState(0);
|
|
1117
|
-
React.
|
|
1198
|
+
const rerun = React.useCallback((freshScenePass) => {
|
|
1118
1199
|
callbacksRanRef.current = false;
|
|
1119
|
-
forceScenePassRebuildRef.current = true;
|
|
1200
|
+
if (freshScenePass) forceScenePassRebuildRef.current = true;
|
|
1201
|
+
setRebuildVersion((v) => v + 1);
|
|
1120
1202
|
}, []);
|
|
1203
|
+
const ownerRef = React.useRef(null);
|
|
1204
|
+
const target = React.useCallback(() => (isOwner ? ownerRef.current : activeOwner(store)) ?? null, [isOwner, store]);
|
|
1121
1205
|
const clearPasses = React.useCallback(() => {
|
|
1122
|
-
|
|
1123
|
-
|
|
1206
|
+
const owner = target();
|
|
1207
|
+
if (!owner) return;
|
|
1208
|
+
owner.passes = {};
|
|
1209
|
+
if (activeOwner(store) === owner) store.setState({ passes: {} });
|
|
1210
|
+
}, [store, target]);
|
|
1124
1211
|
const reset = React.useCallback(() => {
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
scenePassCacheRef.current?.scenePass.dispose();
|
|
1131
|
-
callbacksRanRef.current = false;
|
|
1132
|
-
scenePassCacheRef.current = null;
|
|
1133
|
-
forceScenePassRebuildRef.current = false;
|
|
1134
|
-
}, [store]);
|
|
1212
|
+
const owner = target();
|
|
1213
|
+
if (!owner) return;
|
|
1214
|
+
releaseOwner(owner);
|
|
1215
|
+
if (owner === ownerRef.current) committedReads.current = null;
|
|
1216
|
+
}, [target]);
|
|
1135
1217
|
const rebuild = React.useCallback(() => {
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1218
|
+
if (isOwner) rerun(true);
|
|
1219
|
+
else activeOwner(store)?.rebuild();
|
|
1220
|
+
}, [isOwner, rerun, store]);
|
|
1221
|
+
const hmrVersionRef = React.useRef(hmrVersion);
|
|
1222
|
+
React.useEffect(() => {
|
|
1223
|
+
if (hmrVersionRef.current === hmrVersion) return;
|
|
1224
|
+
hmrVersionRef.current = hmrVersion;
|
|
1225
|
+
if (isOwner) rerun(false);
|
|
1226
|
+
}, [hmrVersion, isOwner, rerun]);
|
|
1227
|
+
const committedReads = React.useRef(null);
|
|
1228
|
+
const readsVersion = React.useRef(0);
|
|
1229
|
+
const getReadsVersion = () => {
|
|
1230
|
+
const tracker = committedReads.current;
|
|
1231
|
+
if (tracker && !tracker.stale && isTrackerStale(tracker, view)) readsVersion.current++;
|
|
1232
|
+
return readsVersion.current;
|
|
1233
|
+
};
|
|
1234
|
+
const subscribe = React.useCallback(
|
|
1235
|
+
(onChange) => {
|
|
1236
|
+
const unsubscribe = primary.subscribe(onChange);
|
|
1237
|
+
if (store === primary) return unsubscribe;
|
|
1238
|
+
const unsubscribeLocal = store.subscribe(onChange);
|
|
1239
|
+
return () => {
|
|
1240
|
+
unsubscribe();
|
|
1241
|
+
unsubscribeLocal();
|
|
1242
|
+
};
|
|
1243
|
+
},
|
|
1244
|
+
[primary, store]
|
|
1245
|
+
);
|
|
1246
|
+
const resourceVersion = React.useSyncExternalStore(subscribe, getReadsVersion, getReadsVersion);
|
|
1247
|
+
const lastResourceVersion = React.useRef(resourceVersion);
|
|
1140
1248
|
React.useLayoutEffect(() => {
|
|
1141
1249
|
if (isLegacy) {
|
|
1142
|
-
throw new Error(
|
|
1250
|
+
throw new Error(
|
|
1251
|
+
"useRenderPipeline needs WebGPU: import Canvas from @react-three/fiber, not @react-three/fiber/legacy."
|
|
1252
|
+
);
|
|
1143
1253
|
}
|
|
1254
|
+
if (!isOwner) return;
|
|
1144
1255
|
if (!renderer || !scene || !camera) return;
|
|
1145
1256
|
if (!("isWebGPURenderer" in renderer)) {
|
|
1146
1257
|
throw new Error("useRenderPipeline: renderer is not a WebGPURenderer but isLegacy is false.");
|
|
1147
1258
|
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1259
|
+
let owner = ownerRef.current;
|
|
1260
|
+
if (owner && owner.store !== store) {
|
|
1261
|
+
releaseOwner(owner);
|
|
1262
|
+
owner = null;
|
|
1263
|
+
}
|
|
1264
|
+
if (!owner) owner = ownerRef.current = createOwner(store, () => rerun(true));
|
|
1265
|
+
claimOwnership(owner);
|
|
1266
|
+
const currentOwner = owner;
|
|
1150
1267
|
try {
|
|
1151
|
-
let pipeline = state.renderPipeline ?? null;
|
|
1152
|
-
let currentPasses = { ...state.passes };
|
|
1153
1268
|
let justCreatedPipeline = false;
|
|
1154
|
-
if (!pipeline) {
|
|
1155
|
-
|
|
1269
|
+
if (!owner.pipeline || owner.pipeline.renderer !== renderer) {
|
|
1270
|
+
disposeOwnerResources(owner);
|
|
1271
|
+
owner.pipeline = new THREE__namespace.RenderPipeline(renderer);
|
|
1156
1272
|
justCreatedPipeline = true;
|
|
1157
1273
|
}
|
|
1158
|
-
const
|
|
1274
|
+
const pipeline = owner.pipeline;
|
|
1275
|
+
const cached = owner.scenePass;
|
|
1276
|
+
const cacheValid = !forceScenePassRebuildRef.current && cached !== null && cached.sceneUuid === scene.uuid && cached.cameraUuid === camera.uuid;
|
|
1159
1277
|
let outgoingScenePass = null;
|
|
1160
1278
|
let scenePass;
|
|
1161
|
-
if (cacheValid) {
|
|
1162
|
-
scenePass =
|
|
1279
|
+
if (cacheValid && cached) {
|
|
1280
|
+
scenePass = cached.node;
|
|
1163
1281
|
} else {
|
|
1164
|
-
outgoingScenePass =
|
|
1282
|
+
outgoingScenePass = cached?.node ?? null;
|
|
1165
1283
|
scenePass = tsl.pass(scene, camera);
|
|
1166
|
-
|
|
1284
|
+
owner.scenePass = { sceneUuid: scene.uuid, cameraUuid: camera.uuid, node: scenePass };
|
|
1167
1285
|
forceScenePassRebuildRef.current = false;
|
|
1168
1286
|
}
|
|
1169
|
-
currentPasses.scenePass = scenePass;
|
|
1170
1287
|
let outputNodeChanged = false;
|
|
1171
1288
|
if (!pipeline.outputNode || justCreatedPipeline || pipeline.outputNode === outgoingScenePass) {
|
|
1172
1289
|
pipeline.outputNode = scenePass;
|
|
1173
1290
|
outputNodeChanged = true;
|
|
1174
1291
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
const shouldRunCallbacks = justCreatedPipeline || !callbacksRanRef.current || !cacheValid;
|
|
1292
|
+
const readsChanged = lastResourceVersion.current !== resourceVersion;
|
|
1293
|
+
lastResourceVersion.current = resourceVersion;
|
|
1294
|
+
const shouldRunCallbacks = justCreatedPipeline || !callbacksRanRef.current || !cacheValid || readsChanged;
|
|
1178
1295
|
if (shouldRunCallbacks) {
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1296
|
+
let currentPasses = { scenePass };
|
|
1297
|
+
owner.passes = currentPasses;
|
|
1298
|
+
const tracker = createReadTracker("useRenderPipeline");
|
|
1299
|
+
const callbackState = () => Object.assign(
|
|
1300
|
+
createLazyCreatorState(store.getState(), primary, {
|
|
1301
|
+
reads: { observe: tracker.observe, nested: true },
|
|
1302
|
+
view
|
|
1303
|
+
}),
|
|
1304
|
+
{ renderPipeline: pipeline, passes: { ...currentPasses, scenePass }, renderer, isLegacy: false }
|
|
1305
|
+
);
|
|
1306
|
+
try {
|
|
1307
|
+
if (setupCBRef.current) {
|
|
1308
|
+
const setupResult = setupCBRef.current(callbackState());
|
|
1309
|
+
if (setupResult && typeof setupResult === "object") {
|
|
1310
|
+
currentPasses = { ...currentPasses, ...setupResult };
|
|
1311
|
+
owner.passes = currentPasses;
|
|
1312
|
+
}
|
|
1190
1313
|
}
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
isLegacy: false
|
|
1198
|
-
});
|
|
1199
|
-
const mainResult = mainCBRef.current(freshState);
|
|
1200
|
-
if (mainResult && typeof mainResult === "object") {
|
|
1201
|
-
currentPasses = { ...currentPasses, ...mainResult };
|
|
1202
|
-
set({ passes: currentPasses });
|
|
1314
|
+
if (mainCBRef.current) {
|
|
1315
|
+
const mainResult = mainCBRef.current(callbackState());
|
|
1316
|
+
if (mainResult && typeof mainResult === "object") {
|
|
1317
|
+
currentPasses = { ...currentPasses, ...mainResult };
|
|
1318
|
+
owner.passes = currentPasses;
|
|
1319
|
+
}
|
|
1203
1320
|
}
|
|
1321
|
+
} finally {
|
|
1322
|
+
tracker.closed = true;
|
|
1323
|
+
committedReads.current = tracker;
|
|
1204
1324
|
}
|
|
1205
1325
|
outputNodeChanged = true;
|
|
1206
1326
|
callbacksRanRef.current = true;
|
|
1207
1327
|
}
|
|
1208
1328
|
if (outputNodeChanged) pipeline.needsUpdate = true;
|
|
1329
|
+
publishOwner(owner);
|
|
1209
1330
|
if (outgoingScenePass && outgoingScenePass !== scenePass) outgoingScenePass.dispose();
|
|
1210
1331
|
} catch (error) {
|
|
1332
|
+
publishOwner(owner);
|
|
1211
1333
|
console.warn("[useRenderPipeline] Setup failed; the render pipeline was not configured:", error);
|
|
1212
1334
|
}
|
|
1213
|
-
|
|
1335
|
+
return () => {
|
|
1336
|
+
if (persistRef.current) currentOwner.mounted = false;
|
|
1337
|
+
else scheduleRelease(currentOwner);
|
|
1338
|
+
};
|
|
1339
|
+
}, [store, primary, view, renderer, scene, camera, isLegacy, isOwner, rebuildVersion, resourceVersion, rerun]);
|
|
1214
1340
|
const passes = extension.useThree((s) => s.passes) ?? NO_PASSES;
|
|
1215
1341
|
const renderPipeline = extension.useThree((s) => s.renderPipeline) ?? null;
|
|
1216
1342
|
const actions = { passes, clearPasses, reset, rebuild };
|