@babylonjs/lite 1.6.0 → 1.8.0
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/CHANGELOG.md +735 -0
- package/README.md +26 -1
- package/THIRD_PARTY_NOTICES.txt +139 -0
- package/dist/index.js +321 -301
- package/dist/index.js.map +1 -1
- package/index.d.ts +294 -13
- package/lib/_chunks/vendor/{manifold-Sh8xE2da.js → manifold-DtI3BJoR.js} +2 -2
- package/lib/_chunks/vendor/{manifold-Sh8xE2da.js.map → manifold-DtI3BJoR.js.map} +1 -1
- package/lib/animation/animation-group-task.js +1 -1
- package/lib/animation/animation-group-task.js.map +1 -1
- package/lib/animation/animation-group.js +20 -15
- package/lib/animation/animation-group.js.map +1 -1
- package/lib/animation/animation-tick.js +10 -0
- package/lib/animation/animation-tick.js.map +1 -0
- package/lib/animation/property-animation.js +2 -1
- package/lib/animation/property-animation.js.map +1 -1
- package/lib/animation/weighted-gltf-mixer.js +1 -1
- package/lib/animation/weighted-gltf-mixer.js.map +1 -1
- package/lib/animation/weighted-pointer-mixer.js +1 -1
- package/lib/animation/weighted-pointer-mixer.js.map +1 -1
- package/lib/engine/device-lost-recovery.js +1 -0
- package/lib/engine/device-lost-recovery.js.map +1 -1
- package/lib/engine/engine.js +1 -1
- package/lib/engine/null-engine.js +29 -0
- package/lib/engine/null-engine.js.map +1 -0
- package/lib/frame-graph/depth-pyramid.js +158 -0
- package/lib/frame-graph/depth-pyramid.js.map +1 -0
- package/lib/frame-graph/depth-resolve-task.js +117 -0
- package/lib/frame-graph/depth-resolve-task.js.map +1 -0
- package/lib/frame-graph/frame-graph-actions.js +10 -1
- package/lib/frame-graph/frame-graph-actions.js.map +1 -1
- package/lib/frame-graph/render-task.js +7 -0
- package/lib/frame-graph/render-task.js.map +1 -1
- package/lib/frame-graph/transmission-depth-grab.js +88 -0
- package/lib/frame-graph/transmission-depth-grab.js.map +1 -0
- package/lib/frame-graph/transmission.js +34 -4
- package/lib/frame-graph/transmission.js.map +1 -1
- package/lib/gizmo/bounding-box-gizmo.js +1 -1
- package/lib/index.js +9 -6
- package/lib/index.js.map +1 -1
- package/lib/loader-gltf/gltf-feature-gpu-instancing.js +1 -1
- package/lib/loader-gltf/gltf-interleave.js +1 -1
- package/lib/loader-gltf/load-gltf.js +1 -1
- package/lib/material/shader/shader-material.js +4 -2
- package/lib/material/shader/shader-material.js.map +1 -1
- package/lib/material/shader/shader-pipeline.js +11 -1
- package/lib/material/shader/shader-pipeline.js.map +1 -1
- package/lib/material/shader/shader-renderable.js +42 -14
- package/lib/material/shader/shader-renderable.js.map +1 -1
- package/lib/material/shader/shader-thin-instance.js +1 -1
- package/lib/material/shader/shader-thin-instance.js.map +1 -1
- package/lib/math/aabb.js +1 -1
- package/lib/math/compute-aabb.js +63 -1
- package/lib/math/compute-aabb.js.map +1 -1
- package/lib/math/index.js +1 -1
- package/lib/mesh/csg2.js +3 -2
- package/lib/mesh/csg2.js.map +1 -1
- package/lib/mesh/mesh-factories.js +1 -1
- package/lib/mesh/thin-instance-gpu-culling.js +4 -2
- package/lib/mesh/thin-instance-gpu-culling.js.map +1 -1
- package/lib/mesh/thin-instance.js +8 -1
- package/lib/mesh/thin-instance.js.map +1 -1
- package/lib/navigation/index.js +1 -1
- package/lib/navigation/navigation.js +9 -1
- package/lib/navigation/navigation.js.map +1 -1
- package/lib/physics/character-controller.js +2 -2
- package/lib/physics/character-controller.js.map +1 -1
- package/lib/physics/havok-floating-origin.js +2 -2
- package/lib/physics/havok-floating-origin.js.map +1 -1
- package/lib/physics/havok.js +40 -13
- package/lib/physics/havok.js.map +1 -1
- package/lib/picking/gpu-picker.js +16 -2
- package/lib/picking/gpu-picker.js.map +1 -1
- package/lib/scene/scene-core.js +14 -5
- package/lib/scene/scene-core.js.map +1 -1
- package/lib/scene/scene-remove.js +8 -0
- package/lib/scene/scene-remove.js.map +1 -1
- package/lib/shadow/csm-shadow-task-hooks.js +14 -6
- package/lib/shadow/csm-shadow-task-hooks.js.map +1 -1
- package/lib/shadow/pcf-shadow-task-hooks.js +6 -0
- package/lib/shadow/pcf-shadow-task-hooks.js.map +1 -1
- package/lib/texture/pixels-texture.js +31 -1
- package/lib/texture/pixels-texture.js.map +1 -1
- package/lib/vat/vat-baker.js +41 -2
- package/lib/vat/vat-baker.js.map +1 -1
- package/package.json +15 -3
- package/lib/_chunks/__vite-browser-external-BFTKbDcV.js +0 -68
- package/lib/_chunks/__vite-browser-external-BFTKbDcV.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"weighted-pointer-mixer.js","sources":["../../../src/animation/weighted-pointer-mixer.ts"],"sourcesContent":["import { F32 } from \"../engine/typed-arrays.js\";\nimport { tickAnimation } from \"./animation-group.js\";\nimport type { AnimationGroup, AnimationPropertyMixer, AnimationPropertyRuntimeTrack } from \"./animation-group.js\";\nimport { ANIMATION_GROUP_TASK_CATEGORY, getAnimationGroups } from \"./animation-group-task.js\";\nimport { setAnimationTaskCategoryHandler } from \"./animation-manager.js\";\nimport type { AnimationManager } from \"./animation-manager.js\";\nimport { evaluateSampler } from \"./evaluate.js\";\n\nconst MIX_TRACKS = 0;\nconst MIX_FROM = 1;\nconst MIX_TO = 2;\nconst MIX_DURATION = 3;\n\ninterface WeightedPointerBucket {\n readonly target: object;\n readonly property: string;\n readonly values: Float32Array;\n writer: (output: Float32Array, offset: number) => void;\n arity: number;\n quaternion: boolean;\n contested: boolean;\n active: boolean;\n hasReference: boolean;\n refX: number;\n refY: number;\n refZ: number;\n refW: number;\n}\n\ninterface WeightedPointerScratch {\n readonly buckets: WeightedPointerBucket[];\n readonly sample: Float32Array;\n readonly fades: AnimationWeightFade[];\n}\n\nlet scratchByManager: WeakMap<AnimationManager, WeightedPointerScratch> | undefined;\n\ninterface AnimationWeightFade {\n readonly group: AnimationGroup;\n readonly from: number;\n readonly to: number;\n readonly durationMs: number;\n elapsedMs: number;\n}\n\n/** Options for {@link fadeAnimationWeight}. */\nexport interface FadeAnimationWeightOptions {\n readonly to: number;\n readonly durationMs: number;\n readonly from?: number;\n}\n\n/** Options for {@link crossFadeAnimationGroups}. */\nexport interface CrossFadeAnimationGroupsOptions {\n readonly durationMs: number;\n readonly toWeight?: number;\n}\n\n/** Enables weighted property-animation blending on `manager` by registering its category handler. */\nexport function enablePropertyAnimationBlending(manager: AnimationManager): void {\n setAnimationTaskCategoryHandler(manager, ANIMATION_GROUP_TASK_CATEGORY, updateWeightedPointerAnimations);\n}\n\nfunction getScratch(manager: AnimationManager): WeightedPointerScratch {\n scratchByManager ??= new WeakMap();\n let scratch = scratchByManager.get(manager);\n if (!scratch) {\n scratch = {\n buckets: [],\n sample: new F32(16),\n fades: [],\n };\n scratchByManager.set(manager, scratch);\n }\n return scratch;\n}\n\n/** Animates `group`'s blend weight toward `options.to` over `options.durationMs`, enabling blending on `manager`.\n * @throws If `to`/`from` are outside `[0, 1]` or the duration is not a finite positive number. */\nexport function fadeAnimationWeight(manager: AnimationManager, group: AnimationGroup, options: FadeAnimationWeightOptions): void {\n const to = validateWeight(options.to);\n const from = options.from === undefined ? group.weight : validateWeight(options.from);\n if (!(options.durationMs > 0) || !Number.isFinite(options.durationMs)) {\n throw new Error(`Animation weight fade duration must be a finite positive number, got ${options.durationMs}`);\n }\n\n enablePropertyAnimationBlending(manager);\n group.weight = from;\n const scratch = getScratch(manager);\n for (let i = scratch.fades.length - 1; i >= 0; i--) {\n if (scratch.fades[i]!.group === group) {\n scratch.fades.splice(i, 1);\n }\n }\n scratch.fades.push({ group, from, to, durationMs: options.durationMs, elapsedMs: 0 });\n}\n\n/** Cross-fades from `fromGroup` to `toGroup`, fading the first to weight 0 and the second to `options.toWeight` (default 1). */\nexport function crossFadeAnimationGroups(manager: AnimationManager, fromGroup: AnimationGroup, toGroup: AnimationGroup, options: CrossFadeAnimationGroupsOptions): void {\n const toWeight = validateWeight(options.toWeight ?? 1);\n fadeAnimationWeight(manager, fromGroup, { to: 0, durationMs: options.durationMs });\n fadeAnimationWeight(manager, toGroup, { to: toWeight, durationMs: options.durationMs });\n}\n\nfunction updateWeightedPointerAnimations(manager: AnimationManager, deltaMs: number): boolean {\n const scratch = getScratch(manager);\n updateFades(scratch, deltaMs);\n let contestedCount = 0;\n\n for (let bucketIndex = 0; bucketIndex < scratch.buckets.length; bucketIndex++) {\n const bucket = scratch.buckets[bucketIndex]!;\n bucket.contested = false;\n bucket.active = false;\n bucket.hasReference = false;\n bucket.values.fill(0);\n }\n\n const groups = getAnimationGroups(manager);\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex]!;\n const mixer = group._propertyMixer;\n if (group._stopped || group.weight === 1 || !mixer) {\n continue;\n }\n const tracks = mixer[MIX_TRACKS];\n for (let trackIndex = 0; trackIndex < tracks.length; trackIndex++) {\n const track = tracks[trackIndex]!;\n const bucket = getTrackBucket(scratch.buckets, track);\n if (!bucket.contested) {\n bucket.contested = true;\n contestedCount++;\n }\n }\n }\n\n if (contestedCount === 0) {\n return false;\n }\n\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex]!;\n if (group._stopped) {\n continue;\n }\n\n const mixer = group._propertyMixer;\n const tracks = mixer?.[MIX_TRACKS];\n if (!tracks) {\n tickAnimation(group, deltaMs, manager.engine);\n continue;\n }\n\n const t = advancePropertyGroupTime(group, mixer, deltaMs);\n const weight = group.weight;\n if (weight === 0) {\n continue;\n }\n\n for (let trackIndex = 0; trackIndex < tracks.length; trackIndex++) {\n const track = tracks[trackIndex]!;\n evaluateSampler(track.sampler, t, track.stride, track.quaternion, scratch.sample, 0);\n const bucket = getTrackBucket(scratch.buckets, track);\n if (!bucket.contested) {\n track.writer(scratch.sample, 0);\n continue;\n }\n if (weight !== 0) {\n accumulateWeightedTrack(bucket, track, scratch.sample, weight);\n }\n }\n }\n\n for (let bucketIndex = 0; bucketIndex < scratch.buckets.length; bucketIndex++) {\n const bucket = scratch.buckets[bucketIndex]!;\n if (!bucket.active) {\n continue;\n }\n if (bucket.quaternion && bucket.arity === 4) {\n normalizeQuaternion(bucket.values);\n }\n bucket.writer(bucket.values, 0);\n }\n\n return true;\n}\n\nfunction updateFades(scratch: WeightedPointerScratch, deltaMs: number): void {\n for (let i = scratch.fades.length - 1; i >= 0; i--) {\n const fade = scratch.fades[i]!;\n fade.elapsedMs = Math.min(fade.durationMs, fade.elapsedMs + Math.max(0, deltaMs));\n const t = fade.elapsedMs / fade.durationMs;\n fade.group.weight = fade.from + (fade.to - fade.from) * t;\n if (fade.elapsedMs >= fade.durationMs) {\n fade.group.weight = fade.to;\n scratch.fades.splice(i, 1);\n }\n }\n}\n\nfunction validateWeight(weight: number): number {\n if (!Number.isFinite(weight) || weight < 0 || weight > 1) {\n throw new Error(`Animation weight must be a finite number between 0 and 1, got ${weight}`);\n }\n return weight;\n}\n\nfunction advancePropertyGroupTime(group: AnimationGroup, mixer: AnimationPropertyMixer, deltaMs: number): number {\n if (group.isPlaying) {\n group.currentTime += (deltaMs / 1000) * group.speedRatio;\n }\n\n const fromTime = Math.max(0, Math.min(mixer[MIX_FROM], mixer[MIX_DURATION]));\n const toTime = mixer[MIX_TO] > fromTime ? Math.min(mixer[MIX_TO], mixer[MIX_DURATION]) : mixer[MIX_DURATION];\n const duration = Math.max(0, toTime - fromTime);\n if (duration <= 0) {\n return fromTime;\n }\n\n if (group.loopAnimation) {\n group.currentTime = fromTime + ((group.currentTime - fromTime) % duration);\n if (group.currentTime < fromTime) {\n group.currentTime += duration;\n }\n } else {\n group.currentTime = Math.min(Math.max(group.currentTime, fromTime), toTime);\n }\n return group.currentTime;\n}\n\nfunction getTrackBucket(buckets: WeightedPointerBucket[], track: AnimationPropertyRuntimeTrack): WeightedPointerBucket {\n const arity = track.stride;\n for (let bucketIndex = 0; bucketIndex < buckets.length; bucketIndex++) {\n const candidate = buckets[bucketIndex]!;\n if (candidate.target === track.mixTarget && candidate.property === track.mixProperty) {\n if (candidate.arity !== arity) {\n throw new Error(\"Weighted animation channels for the same property must use the same value size\");\n }\n candidate.writer = track.writer;\n candidate.quaternion = track.quaternion;\n return candidate;\n }\n }\n\n const bucket: WeightedPointerBucket = {\n target: track.mixTarget,\n property: track.mixProperty,\n values: new F32(arity),\n writer: track.writer,\n arity,\n quaternion: track.quaternion,\n contested: false,\n active: false,\n hasReference: false,\n refX: 0,\n refY: 0,\n refZ: 0,\n refW: 1,\n };\n buckets.push(bucket);\n return bucket;\n}\n\nfunction accumulateWeightedTrack(bucket: WeightedPointerBucket, track: AnimationPropertyRuntimeTrack, sample: Float32Array, weight: number): void {\n bucket.active = true;\n\n let sign = 1;\n if (bucket.quaternion && track.stride === 4) {\n if (!bucket.hasReference) {\n bucket.refX = sample[0]!;\n bucket.refY = sample[1]!;\n bucket.refZ = sample[2]!;\n bucket.refW = sample[3]!;\n bucket.hasReference = true;\n } else {\n const dot = bucket.refX * sample[0]! + bucket.refY * sample[1]! + bucket.refZ * sample[2]! + bucket.refW * sample[3]!;\n sign = dot < 0 ? -1 : 1;\n }\n }\n\n for (let i = 0; i < track.stride; i++) {\n bucket.values[i] = bucket.values[i]! + sample[i]! * weight * sign;\n }\n}\n\nfunction normalizeQuaternion(values: Float32Array): void {\n const x = values[0]!;\n const y = values[1]!;\n const z = values[2]!;\n const w = values[3]!;\n const lenSq = x * x + y * y + z * z + w * w;\n if (lenSq > 0) {\n const inv = 1 / Math.sqrt(lenSq);\n values[0] = x * inv;\n values[1] = y * inv;\n values[2] = z * inv;\n values[3] = w * inv;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"weighted-pointer-mixer.js","sources":["../../../src/animation/weighted-pointer-mixer.ts"],"sourcesContent":["import { F32 } from \"../engine/typed-arrays.js\";\nimport { tickAnimation } from \"./animation-tick.js\";\nimport type { AnimationGroup, AnimationPropertyMixer, AnimationPropertyRuntimeTrack } from \"./animation-group.js\";\nimport { ANIMATION_GROUP_TASK_CATEGORY, getAnimationGroups } from \"./animation-group-task.js\";\nimport { setAnimationTaskCategoryHandler } from \"./animation-manager.js\";\nimport type { AnimationManager } from \"./animation-manager.js\";\nimport { evaluateSampler } from \"./evaluate.js\";\n\nconst MIX_TRACKS = 0;\nconst MIX_FROM = 1;\nconst MIX_TO = 2;\nconst MIX_DURATION = 3;\n\ninterface WeightedPointerBucket {\n readonly target: object;\n readonly property: string;\n readonly values: Float32Array;\n writer: (output: Float32Array, offset: number) => void;\n arity: number;\n quaternion: boolean;\n contested: boolean;\n active: boolean;\n hasReference: boolean;\n refX: number;\n refY: number;\n refZ: number;\n refW: number;\n}\n\ninterface WeightedPointerScratch {\n readonly buckets: WeightedPointerBucket[];\n readonly sample: Float32Array;\n readonly fades: AnimationWeightFade[];\n}\n\nlet scratchByManager: WeakMap<AnimationManager, WeightedPointerScratch> | undefined;\n\ninterface AnimationWeightFade {\n readonly group: AnimationGroup;\n readonly from: number;\n readonly to: number;\n readonly durationMs: number;\n elapsedMs: number;\n}\n\n/** Options for {@link fadeAnimationWeight}. */\nexport interface FadeAnimationWeightOptions {\n readonly to: number;\n readonly durationMs: number;\n readonly from?: number;\n}\n\n/** Options for {@link crossFadeAnimationGroups}. */\nexport interface CrossFadeAnimationGroupsOptions {\n readonly durationMs: number;\n readonly toWeight?: number;\n}\n\n/** Enables weighted property-animation blending on `manager` by registering its category handler. */\nexport function enablePropertyAnimationBlending(manager: AnimationManager): void {\n setAnimationTaskCategoryHandler(manager, ANIMATION_GROUP_TASK_CATEGORY, updateWeightedPointerAnimations);\n}\n\nfunction getScratch(manager: AnimationManager): WeightedPointerScratch {\n scratchByManager ??= new WeakMap();\n let scratch = scratchByManager.get(manager);\n if (!scratch) {\n scratch = {\n buckets: [],\n sample: new F32(16),\n fades: [],\n };\n scratchByManager.set(manager, scratch);\n }\n return scratch;\n}\n\n/** Animates `group`'s blend weight toward `options.to` over `options.durationMs`, enabling blending on `manager`.\n * @throws If `to`/`from` are outside `[0, 1]` or the duration is not a finite positive number. */\nexport function fadeAnimationWeight(manager: AnimationManager, group: AnimationGroup, options: FadeAnimationWeightOptions): void {\n const to = validateWeight(options.to);\n const from = options.from === undefined ? group.weight : validateWeight(options.from);\n if (!(options.durationMs > 0) || !Number.isFinite(options.durationMs)) {\n throw new Error(`Animation weight fade duration must be a finite positive number, got ${options.durationMs}`);\n }\n\n enablePropertyAnimationBlending(manager);\n group.weight = from;\n const scratch = getScratch(manager);\n for (let i = scratch.fades.length - 1; i >= 0; i--) {\n if (scratch.fades[i]!.group === group) {\n scratch.fades.splice(i, 1);\n }\n }\n scratch.fades.push({ group, from, to, durationMs: options.durationMs, elapsedMs: 0 });\n}\n\n/** Cross-fades from `fromGroup` to `toGroup`, fading the first to weight 0 and the second to `options.toWeight` (default 1). */\nexport function crossFadeAnimationGroups(manager: AnimationManager, fromGroup: AnimationGroup, toGroup: AnimationGroup, options: CrossFadeAnimationGroupsOptions): void {\n const toWeight = validateWeight(options.toWeight ?? 1);\n fadeAnimationWeight(manager, fromGroup, { to: 0, durationMs: options.durationMs });\n fadeAnimationWeight(manager, toGroup, { to: toWeight, durationMs: options.durationMs });\n}\n\nfunction updateWeightedPointerAnimations(manager: AnimationManager, deltaMs: number): boolean {\n const scratch = getScratch(manager);\n updateFades(scratch, deltaMs);\n let contestedCount = 0;\n\n for (let bucketIndex = 0; bucketIndex < scratch.buckets.length; bucketIndex++) {\n const bucket = scratch.buckets[bucketIndex]!;\n bucket.contested = false;\n bucket.active = false;\n bucket.hasReference = false;\n bucket.values.fill(0);\n }\n\n const groups = getAnimationGroups(manager);\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex]!;\n const mixer = group._propertyMixer;\n if (group._stopped || group.weight === 1 || !mixer) {\n continue;\n }\n const tracks = mixer[MIX_TRACKS];\n for (let trackIndex = 0; trackIndex < tracks.length; trackIndex++) {\n const track = tracks[trackIndex]!;\n const bucket = getTrackBucket(scratch.buckets, track);\n if (!bucket.contested) {\n bucket.contested = true;\n contestedCount++;\n }\n }\n }\n\n if (contestedCount === 0) {\n return false;\n }\n\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex]!;\n if (group._stopped) {\n continue;\n }\n\n const mixer = group._propertyMixer;\n const tracks = mixer?.[MIX_TRACKS];\n if (!tracks) {\n tickAnimation(group, deltaMs, manager.engine);\n continue;\n }\n\n const t = advancePropertyGroupTime(group, mixer, deltaMs);\n const weight = group.weight;\n if (weight === 0) {\n continue;\n }\n\n for (let trackIndex = 0; trackIndex < tracks.length; trackIndex++) {\n const track = tracks[trackIndex]!;\n evaluateSampler(track.sampler, t, track.stride, track.quaternion, scratch.sample, 0);\n const bucket = getTrackBucket(scratch.buckets, track);\n if (!bucket.contested) {\n track.writer(scratch.sample, 0);\n continue;\n }\n if (weight !== 0) {\n accumulateWeightedTrack(bucket, track, scratch.sample, weight);\n }\n }\n }\n\n for (let bucketIndex = 0; bucketIndex < scratch.buckets.length; bucketIndex++) {\n const bucket = scratch.buckets[bucketIndex]!;\n if (!bucket.active) {\n continue;\n }\n if (bucket.quaternion && bucket.arity === 4) {\n normalizeQuaternion(bucket.values);\n }\n bucket.writer(bucket.values, 0);\n }\n\n return true;\n}\n\nfunction updateFades(scratch: WeightedPointerScratch, deltaMs: number): void {\n for (let i = scratch.fades.length - 1; i >= 0; i--) {\n const fade = scratch.fades[i]!;\n fade.elapsedMs = Math.min(fade.durationMs, fade.elapsedMs + Math.max(0, deltaMs));\n const t = fade.elapsedMs / fade.durationMs;\n fade.group.weight = fade.from + (fade.to - fade.from) * t;\n if (fade.elapsedMs >= fade.durationMs) {\n fade.group.weight = fade.to;\n scratch.fades.splice(i, 1);\n }\n }\n}\n\nfunction validateWeight(weight: number): number {\n if (!Number.isFinite(weight) || weight < 0 || weight > 1) {\n throw new Error(`Animation weight must be a finite number between 0 and 1, got ${weight}`);\n }\n return weight;\n}\n\nfunction advancePropertyGroupTime(group: AnimationGroup, mixer: AnimationPropertyMixer, deltaMs: number): number {\n if (group.isPlaying) {\n group.currentTime += (deltaMs / 1000) * group.speedRatio;\n }\n\n const fromTime = Math.max(0, Math.min(mixer[MIX_FROM], mixer[MIX_DURATION]));\n const toTime = mixer[MIX_TO] > fromTime ? Math.min(mixer[MIX_TO], mixer[MIX_DURATION]) : mixer[MIX_DURATION];\n const duration = Math.max(0, toTime - fromTime);\n if (duration <= 0) {\n return fromTime;\n }\n\n if (group.loopAnimation) {\n group.currentTime = fromTime + ((group.currentTime - fromTime) % duration);\n if (group.currentTime < fromTime) {\n group.currentTime += duration;\n }\n } else {\n group.currentTime = Math.min(Math.max(group.currentTime, fromTime), toTime);\n }\n return group.currentTime;\n}\n\nfunction getTrackBucket(buckets: WeightedPointerBucket[], track: AnimationPropertyRuntimeTrack): WeightedPointerBucket {\n const arity = track.stride;\n for (let bucketIndex = 0; bucketIndex < buckets.length; bucketIndex++) {\n const candidate = buckets[bucketIndex]!;\n if (candidate.target === track.mixTarget && candidate.property === track.mixProperty) {\n if (candidate.arity !== arity) {\n throw new Error(\"Weighted animation channels for the same property must use the same value size\");\n }\n candidate.writer = track.writer;\n candidate.quaternion = track.quaternion;\n return candidate;\n }\n }\n\n const bucket: WeightedPointerBucket = {\n target: track.mixTarget,\n property: track.mixProperty,\n values: new F32(arity),\n writer: track.writer,\n arity,\n quaternion: track.quaternion,\n contested: false,\n active: false,\n hasReference: false,\n refX: 0,\n refY: 0,\n refZ: 0,\n refW: 1,\n };\n buckets.push(bucket);\n return bucket;\n}\n\nfunction accumulateWeightedTrack(bucket: WeightedPointerBucket, track: AnimationPropertyRuntimeTrack, sample: Float32Array, weight: number): void {\n bucket.active = true;\n\n let sign = 1;\n if (bucket.quaternion && track.stride === 4) {\n if (!bucket.hasReference) {\n bucket.refX = sample[0]!;\n bucket.refY = sample[1]!;\n bucket.refZ = sample[2]!;\n bucket.refW = sample[3]!;\n bucket.hasReference = true;\n } else {\n const dot = bucket.refX * sample[0]! + bucket.refY * sample[1]! + bucket.refZ * sample[2]! + bucket.refW * sample[3]!;\n sign = dot < 0 ? -1 : 1;\n }\n }\n\n for (let i = 0; i < track.stride; i++) {\n bucket.values[i] = bucket.values[i]! + sample[i]! * weight * sign;\n }\n}\n\nfunction normalizeQuaternion(values: Float32Array): void {\n const x = values[0]!;\n const y = values[1]!;\n const z = values[2]!;\n const w = values[3]!;\n const lenSq = x * x + y * y + z * z + w * w;\n if (lenSq > 0) {\n const inv = 1 / Math.sqrt(lenSq);\n values[0] = x * inv;\n values[1] = y * inv;\n values[2] = z * inv;\n values[3] = w * inv;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -165,6 +165,7 @@ async function rebuildSceneGpu(engine, scene) {
|
|
|
165
165
|
scene._renderables.length = 0;
|
|
166
166
|
scene._uniformUpdaters.length = 0;
|
|
167
167
|
scene._meshDisposables.clear();
|
|
168
|
+
scene._meshAuxDisposables.clear();
|
|
168
169
|
if (scene._lightGpuState) {
|
|
169
170
|
scene._lightGpuState = void 0;
|
|
170
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-lost-recovery.js","sources":["../../../src/engine/device-lost-recovery.ts"],"sourcesContent":["import { U8 } from \"./typed-arrays.js\";\nimport { TU, BU } from \"./gpu-flags.js\";\nimport type { EngineContext } from \"./engine.js\";\nimport { startEngine, stopEngine, resizeEngine } from \"./engine.js\";\nimport { _refreshScRT } from \"./surface.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { isRenderingContextRegistered } from \"./engine.js\";\nimport type { Mesh, MeshGPU } from \"../mesh/mesh.js\";\nimport { createEmptyUniformBuffer, createMappedBuffer } from \"../resource/gpu-buffers.js\";\nimport { clearSceneBGLCache, getSceneBindGroupLayout } from \"../render/scene-helpers.js\";\nimport { ensureSceneLightState } from \"../render/lights-ubo.js\";\nimport { SCENE_UBO_BYTES } from \"../shader/scene-uniforms-size.js\";\nimport type { Texture2D, Texture2DOptions } from \"../texture/texture-2d.js\";\nimport { getOrCreateSampler } from \"../resource/gpu-pool.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\nimport type { createSkeleton } from \"../skeleton/create-skeleton.js\";\nimport type { createMorphTargets } from \"../morph/create-morph-targets.js\";\n\nexport interface DeviceLostRecoveryOptions {\n onLost?: (info: GPUDeviceLostInfo) => void;\n onRecovered?: () => void;\n onRecoveryFailed?: (error: unknown) => void;\n}\n\nexport interface DeviceLostRecoveryHandle {\n disable(): void;\n}\n\ninterface MutableSkeleton {\n boneTexture: GPUTexture;\n jointsBuffer: GPUBuffer;\n weightsBuffer: GPUBuffer;\n joints1Buffer: GPUBuffer | null;\n weights1Buffer: GPUBuffer | null;\n}\n\ninterface MutableMorphTargets {\n deltasBuffer: GPUBuffer;\n weightsBuffer: GPUBuffer;\n}\n\ninterface RecoverableRenderTask {\n _sceneUBO: GPUBuffer;\n _sceneBG: GPUBindGroup;\n _lightsUBO: GPUBuffer;\n _opaqueBindings: unknown[];\n _directBindings: unknown[];\n _transparentBindings: unknown[];\n _opaqueBundles: unknown[];\n _lastVersion: number;\n _su: unknown[];\n}\n\ninterface RecoveryState {\n enabled: boolean;\n recovering: boolean;\n forceNextLoss: boolean;\n requiredFeatures: GPUFeatureName[];\n armedDevice: GPUDevice | null;\n options: DeviceLostRecoveryOptions;\n}\n\nlet _states: WeakMap<EngineContext, RecoveryState> | null = null;\n\nfunction states(): WeakMap<EngineContext, RecoveryState> {\n if (!_states) {\n _states = new WeakMap();\n }\n return _states;\n}\n\nfunction getState(engine: EngineContext): RecoveryState {\n let state = states().get(engine);\n if (!state) {\n state = {\n enabled: false,\n recovering: false,\n forceNextLoss: false,\n requiredFeatures: [],\n armedDevice: null,\n options: {},\n };\n states().set(engine, state);\n }\n return state;\n}\n\nexport function enableDeviceLostRecovery(engine: EngineContext, options: DeviceLostRecoveryOptions = {}): DeviceLostRecoveryHandle {\n const state = getState(engine);\n state.enabled = true;\n state.options = options;\n state.requiredFeatures = Array.from(engine._device.features) as GPUFeatureName[];\n attachRecoveryCapture(engine);\n\n arm(engine, state);\n return {\n disable(): void {\n state.enabled = false;\n detachRecoveryCapture(engine);\n },\n };\n}\n\nfunction attachRecoveryCapture(engine: EngineContext): void {\n engine._dlr = {\n u(tex, url, opts) {\n tex._recoverySource = { kind: \"url\", url, opts: { ...opts } };\n },\n s(tex, r, g, b, a) {\n tex._recoverySource = { kind: \"solid\", rgba: [r, g, b, a] };\n },\n b(tex, bitmap, srgb, mipMaps, fallback) {\n tex._recoverySource = {\n kind: \"bitmap\",\n bitmap,\n srgb,\n mipMaps,\n fallback,\n samplerDesc: { magFilter: \"linear\", minFilter: \"linear\", mipmapFilter: \"linear\", addressModeU: \"repeat\", addressModeV: \"repeat\", maxAnisotropy: 4 },\n };\n },\n m(mesh, uv2s, tangents, colors, gpuIndices, indexFormat) {\n mesh._cpuUv2s = uv2s;\n mesh._cpuTangents = tangents;\n mesh._cpuColors = colors;\n mesh._cpuGpuIndices = gpuIndices;\n mesh._cpuIndexFormat = indexFormat;\n },\n };\n}\n\nfunction detachRecoveryCapture(engine: EngineContext): void {\n engine._dlr = undefined;\n}\n\nexport function markNextDeviceLossForRecovery(engine: EngineContext): boolean {\n const state = _states?.get(engine as EngineContext);\n if (!state?.enabled) {\n return false;\n }\n state.forceNextLoss = true;\n return true;\n}\n\nfunction arm(engine: EngineContext, state: RecoveryState): void {\n const device = engine._device;\n if (state.armedDevice === device) {\n return;\n }\n state.armedDevice = device;\n void device.lost.then(async (info) => {\n if (!state.enabled || state.armedDevice !== device) {\n return;\n }\n const forced = state.forceNextLoss;\n state.forceNextLoss = false;\n if (info.reason === \"destroyed\" && !forced) {\n return;\n }\n state.options.onLost?.(info);\n try {\n await recoverDevice(engine, state);\n if (state.enabled) {\n arm(engine, state);\n }\n state.options.onRecovered?.();\n } catch (error) {\n state.options.onRecoveryFailed?.(error);\n }\n });\n}\n\nasync function recoverDevice(engine: EngineContext, state: RecoveryState): Promise<void> {\n if (state.recovering) {\n return;\n }\n state.recovering = true;\n const wasRunning = engine._renderFn !== null;\n stopEngine(engine);\n\n try {\n const adapter = await navigator.gpu.requestAdapter({ powerPreference: \"high-performance\" });\n if (!adapter) {\n throw new Error(\"WebGPU adapter not available during device recovery\");\n }\n const missingFeatures = state.requiredFeatures.filter((f) => !adapter.features.has(f));\n if (missingFeatures.length > 0) {\n throw new Error(`WebGPU device recovery missing required features: ${missingFeatures.join(\", \")}`);\n }\n engine._device = await adapter.requestDevice({ requiredFeatures: state.requiredFeatures });\n // Reconfigure every surface's canvas context against the new device and re-acquire\n // its swapchain texture (the previous device's textures are invalid). The rebuilt\n // frame graphs need fresh color attachments. Per-surface `_swapchainCopySrc` is\n // honoured so surfaces that had been promoted to COPY_SRC for screenshot readback\n // keep that capability across recovery; surfaces that never captured stay\n // RENDER_ATTACHMENT-only.\n for (const surface of engine.surfaces) {\n const usage = surface._swapchainCopySrc ? TU.RENDER_ATTACHMENT | TU.COPY_SRC : TU.RENDER_ATTACHMENT;\n surface._context.configure({\n device: engine._device,\n format: surface._configureFormat,\n alphaMode: surface._alphaMode,\n usage,\n viewFormats: [surface.format],\n });\n _refreshScRT(surface);\n }\n clearSceneBGLCache();\n resizeEngine(engine);\n\n await rebuildRegisteredScenes(engine);\n } finally {\n state.recovering = false;\n }\n\n if (wasRunning) {\n await startEngine(engine);\n }\n}\n\nasync function rebuildRegisteredScenes(engine: EngineContext): Promise<void> {\n for (const surface of engine.surfaces) {\n for (const ctx of surface._renderingContexts) {\n const scene = ctx as SceneContext;\n if (!isRenderingContextRegistered(surface, scene)) {\n continue;\n }\n await rebuildSceneGpu(engine, scene);\n }\n }\n}\n\nasync function rebuildSceneGpu(engine: EngineContext, scene: SceneContext): Promise<void> {\n await rebuildSceneTextures(engine, scene);\n await rebuildMeshes(engine, scene);\n\n scene._renderables.length = 0;\n scene._uniformUpdaters.length = 0;\n scene._meshDisposables.clear();\n if (scene._lightGpuState) {\n scene._lightGpuState = undefined;\n }\n\n for (const [build, meshes] of scene._groups) {\n const result = await build(scene, meshes);\n scene._renderables.push(...result.renderables);\n if (result.updater) {\n scene._uniformUpdaters.push(result.updater);\n }\n }\n scene._renderables.sort((a, b) => a.order - b.order);\n scene._renderableVersion++;\n resetFrameGraphTasks(engine, scene);\n scene._frameGraph.build();\n}\n\nfunction resetFrameGraphTasks(engine: EngineContext, scene: SceneContext): void {\n for (const task of scene._frameGraph._tasks) {\n if (!(\"_sceneUBO\" in task && \"_sceneBG\" in task && \"_opaqueBindings\" in task)) {\n continue;\n }\n const rt = task as unknown as RecoverableRenderTask;\n rt._sceneUBO = createEmptyUniformBuffer(engine, SCENE_UBO_BYTES);\n rt._lightsUBO = ensureSceneLightState(engine, scene)._buffer;\n rt._sceneBG = engine._device.createBindGroup({\n layout: getSceneBindGroupLayout(engine),\n entries: [\n { binding: 0, resource: { buffer: rt._sceneUBO } },\n { binding: 1, resource: { buffer: rt._lightsUBO } },\n ],\n });\n rt._opaqueBindings.length = 0;\n rt._directBindings.length = 0;\n rt._transparentBindings.length = 0;\n rt._opaqueBundles.length = 0;\n rt._lastVersion = -1;\n rt._su.length = 0;\n }\n}\n\nasync function rebuildMeshes(engine: EngineContext, scene: SceneContext): Promise<void> {\n let skeletonFactory: typeof createSkeleton | null = null;\n let morphFactory: typeof createMorphTargets | null = null;\n\n for (const mesh of scene.meshes) {\n if (mesh._cpuPositions && mesh._cpuNormals && mesh._cpuIndices) {\n mesh._gpu = uploadRetainedMesh(engine, mesh);\n }\n if (mesh.skeleton) {\n skeletonFactory ??= (await import(\"../skeleton/create-skeleton.js\")).createSkeleton;\n const old = mesh.skeleton;\n const rebuilt = skeletonFactory(engine, old.joints, old.weights, old.boneCount, old.boneMatrices, old.joints1, old.weights1);\n Object.assign(old as MutableSkeleton, rebuilt);\n }\n if (mesh.morphTargets) {\n morphFactory ??= (await import(\"../morph/create-morph-targets.js\")).createMorphTargets;\n const old = mesh.morphTargets;\n const rebuilt = morphFactory(\n engine,\n old.targets.map((t) => ({ positions: t.positions, normals: t.normals })),\n mesh._cpuPositions ? mesh._cpuPositions.length / 3 : 0,\n Array.from(old.weights)\n );\n Object.assign(old as MutableMorphTargets, rebuilt);\n }\n }\n}\n\nfunction uploadRetainedMesh(engine: EngineContext, mesh: Mesh): MeshGPU {\n const positions = mesh._cpuPositions!;\n const normals = mesh._cpuNormals!;\n const uvs = mesh._cpuUvs;\n const indices = mesh._cpuGpuIndices ?? mesh._cpuIndices!;\n const device = engine._device;\n let uvBuffer: GPUBuffer;\n if (uvs && uvs.length > 0) {\n uvBuffer = createMappedBuffer(engine, uvs, BU.VERTEX);\n } else {\n uvBuffer = device.createBuffer({ size: (positions.length / 3) * 8, usage: BU.VERTEX, mappedAtCreation: true });\n uvBuffer.unmap();\n }\n return {\n positionBuffer: createMappedBuffer(engine, positions, BU.VERTEX),\n normalBuffer: createMappedBuffer(engine, normals, BU.VERTEX),\n tangentBuffer: mesh._cpuTangents ? createMappedBuffer(engine, mesh._cpuTangents, BU.VERTEX) : null,\n uvBuffer,\n uv2Buffer: mesh._cpuUv2s ? createMappedBuffer(engine, mesh._cpuUv2s, BU.VERTEX) : null,\n colorBuffer: mesh._cpuColors ? createMappedBuffer(engine, mesh._cpuColors, BU.VERTEX) : null,\n hasUv: !!uvs && uvs.length > 0,\n hasUv2: !!mesh._cpuUv2s && mesh._cpuUv2s.length > 0,\n hasTangent: !!mesh._cpuTangents && mesh._cpuTangents.length > 0,\n hasColor: !!mesh._cpuColors && mesh._cpuColors.length > 0,\n indexBuffer: createMappedBuffer(engine, indices, BU.INDEX),\n indexCount: mesh._gpu.indexCount,\n indexFormat: mesh._cpuIndexFormat ?? mesh._gpu.indexFormat,\n };\n}\n\nasync function rebuildTexture2D(engine: EngineContext, tex: Texture2D): Promise<void> {\n const source = tex._recoverySource;\n if (!source) {\n return;\n }\n if (source.kind === \"url\") {\n const rebuilt = await rebuildUrlTexture2D(engine, source.url, source.opts);\n tex.texture = rebuilt.texture;\n tex.view = rebuilt.view;\n tex.sampler = rebuilt.sampler;\n tex.width = rebuilt.width;\n tex.height = rebuilt.height;\n tex._recoverySource = source;\n return;\n }\n if (source.kind === \"solid\") {\n const texture = engine._device.createTexture({ size: { width: 1, height: 1 }, format: \"rgba8unorm\", usage: TU.TEXTURE_BINDING | TU.COPY_DST });\n const data = new U8(source.rgba.map((v) => Math.round(v * 255)));\n engine._device.queue.writeTexture({ texture }, data, { bytesPerRow: 4, rowsPerImage: 1 }, { width: 1, height: 1 });\n tex.texture = texture;\n tex.view = texture.createView();\n tex.sampler = getBilinearSampler(engine);\n tex.width = 1;\n tex.height = 1;\n return;\n }\n const width = source.bitmap?.width ?? 1;\n const height = source.bitmap?.height ?? 1;\n const format: GPUTextureFormat = source.srgb ? \"rgba8unorm-srgb\" : \"rgba8unorm\";\n const mipLevelCount = source.mipMaps ? Math.floor(Math.log2(Math.max(width, height))) + 1 : 1;\n const texture = engine._device.createTexture({\n size: { width, height },\n format,\n mipLevelCount,\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.COPY_SRC | TU.RENDER_ATTACHMENT,\n });\n if (source.bitmap) {\n engine._device.queue.copyExternalImageToTexture({ source: source.bitmap }, { texture, premultipliedAlpha: false }, { width, height });\n if (source.mipMaps && mipLevelCount > 1) {\n const { generateMipmaps } = await import(\"../texture/generate-mipmaps.js\");\n generateMipmaps(engine, texture);\n }\n } else {\n engine._device.queue.writeTexture({ texture }, (source.fallback ?? new U8([255, 255, 255, 255])) as Uint8Array<ArrayBuffer>, { bytesPerRow: 4 }, { width: 1, height: 1 });\n }\n tex.texture = texture;\n tex.view = texture.createView();\n tex.sampler = getOrCreateSampler(engine, source.samplerDesc);\n tex.width = width;\n tex.height = height;\n}\n\nasync function rebuildUrlTexture2D(engine: EngineContext, url: string, opts: Texture2DOptions): Promise<Texture2D> {\n const mipMaps = opts.mipMaps ?? true;\n const addressModeU = opts.addressModeU ?? \"repeat\";\n const addressModeV = opts.addressModeV ?? \"repeat\";\n const invertY = opts.invertY ?? true;\n const srgb = opts.srgb ?? false;\n const premultiplyAlpha = opts.premultiplyAlpha ?? false;\n const format: GPUTextureFormat = srgb ? \"rgba8unorm-srgb\" : \"rgba8unorm\";\n\n const response = await fetch(url);\n const blob = await response.blob();\n const imageBitmap = await createImageBitmap(blob, {\n premultiplyAlpha: premultiplyAlpha ? \"premultiply\" : \"none\",\n colorSpaceConversion: \"none\",\n });\n\n const width = imageBitmap.width;\n const height = imageBitmap.height;\n const mipLevelCount = mipMaps ? Math.floor(Math.log2(Math.max(width, height))) + 1 : 1;\n const texture = engine._device.createTexture({\n size: { width, height },\n format,\n mipLevelCount,\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.RENDER_ATTACHMENT,\n });\n engine._device.queue.copyExternalImageToTexture({ source: imageBitmap, flipY: invertY }, { texture, premultipliedAlpha: premultiplyAlpha }, { width, height });\n imageBitmap.close();\n\n if (mipMaps && mipLevelCount > 1) {\n const { generateMipmaps } = await import(\"../texture/generate-mipmaps.js\");\n generateMipmaps(engine, texture);\n }\n\n const minF = opts.minFilter ?? \"linear\";\n const magF = opts.magFilter ?? \"linear\";\n const mipF: GPUMipmapFilterMode = mipMaps ? \"linear\" : \"nearest\";\n const allLinear = minF === \"linear\" && magF === \"linear\" && mipF === \"linear\";\n const sampler = getOrCreateSampler(engine, {\n addressModeU,\n addressModeV,\n minFilter: minF,\n magFilter: magF,\n mipmapFilter: mipF,\n maxAnisotropy: allLinear ? 4 : 1,\n });\n\n return { texture, view: texture.createView(), sampler, width, height };\n}\n\nasync function rebuildSceneTextures(engine: EngineContext, scene: SceneContext): Promise<void> {\n const seen = new Set<Texture2D>();\n const visited = new WeakSet<object>();\n const promises: Promise<void>[] = [];\n const visit = (value: unknown): void => {\n if (!value || typeof value !== \"object\") {\n return;\n }\n const obj = value as Record<string, unknown>;\n if (obj.texture && obj.view && obj.sampler && typeof obj.width === \"number\" && typeof obj.height === \"number\") {\n const tex = obj as unknown as Texture2D;\n if (!seen.has(tex)) {\n seen.add(tex);\n promises.push(rebuildTexture2D(engine, tex));\n }\n return;\n }\n if (visited.has(value)) {\n return;\n }\n visited.add(value);\n for (const child of Object.values(obj)) {\n visit(child);\n }\n };\n for (const mesh of scene.meshes) {\n visit(mesh.material);\n }\n await Promise.all(promises);\n}\n"],"names":["texture"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"device-lost-recovery.js","sources":["../../../src/engine/device-lost-recovery.ts"],"sourcesContent":["import { U8 } from \"./typed-arrays.js\";\nimport { TU, BU } from \"./gpu-flags.js\";\nimport type { EngineContext } from \"./engine.js\";\nimport { startEngine, stopEngine, resizeEngine } from \"./engine.js\";\nimport { _refreshScRT } from \"./surface.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { isRenderingContextRegistered } from \"./engine.js\";\nimport type { Mesh, MeshGPU } from \"../mesh/mesh.js\";\nimport { createEmptyUniformBuffer, createMappedBuffer } from \"../resource/gpu-buffers.js\";\nimport { clearSceneBGLCache, getSceneBindGroupLayout } from \"../render/scene-helpers.js\";\nimport { ensureSceneLightState } from \"../render/lights-ubo.js\";\nimport { SCENE_UBO_BYTES } from \"../shader/scene-uniforms-size.js\";\nimport type { Texture2D, Texture2DOptions } from \"../texture/texture-2d.js\";\nimport { getOrCreateSampler } from \"../resource/gpu-pool.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\nimport type { createSkeleton } from \"../skeleton/create-skeleton.js\";\nimport type { createMorphTargets } from \"../morph/create-morph-targets.js\";\n\nexport interface DeviceLostRecoveryOptions {\n onLost?: (info: GPUDeviceLostInfo) => void;\n onRecovered?: () => void;\n onRecoveryFailed?: (error: unknown) => void;\n}\n\nexport interface DeviceLostRecoveryHandle {\n disable(): void;\n}\n\ninterface MutableSkeleton {\n boneTexture: GPUTexture;\n jointsBuffer: GPUBuffer;\n weightsBuffer: GPUBuffer;\n joints1Buffer: GPUBuffer | null;\n weights1Buffer: GPUBuffer | null;\n}\n\ninterface MutableMorphTargets {\n deltasBuffer: GPUBuffer;\n weightsBuffer: GPUBuffer;\n}\n\ninterface RecoverableRenderTask {\n _sceneUBO: GPUBuffer;\n _sceneBG: GPUBindGroup;\n _lightsUBO: GPUBuffer;\n _opaqueBindings: unknown[];\n _directBindings: unknown[];\n _transparentBindings: unknown[];\n _opaqueBundles: unknown[];\n _lastVersion: number;\n _su: unknown[];\n}\n\ninterface RecoveryState {\n enabled: boolean;\n recovering: boolean;\n forceNextLoss: boolean;\n requiredFeatures: GPUFeatureName[];\n armedDevice: GPUDevice | null;\n options: DeviceLostRecoveryOptions;\n}\n\nlet _states: WeakMap<EngineContext, RecoveryState> | null = null;\n\nfunction states(): WeakMap<EngineContext, RecoveryState> {\n if (!_states) {\n _states = new WeakMap();\n }\n return _states;\n}\n\nfunction getState(engine: EngineContext): RecoveryState {\n let state = states().get(engine);\n if (!state) {\n state = {\n enabled: false,\n recovering: false,\n forceNextLoss: false,\n requiredFeatures: [],\n armedDevice: null,\n options: {},\n };\n states().set(engine, state);\n }\n return state;\n}\n\nexport function enableDeviceLostRecovery(engine: EngineContext, options: DeviceLostRecoveryOptions = {}): DeviceLostRecoveryHandle {\n const state = getState(engine);\n state.enabled = true;\n state.options = options;\n state.requiredFeatures = Array.from(engine._device.features) as GPUFeatureName[];\n attachRecoveryCapture(engine);\n\n arm(engine, state);\n return {\n disable(): void {\n state.enabled = false;\n detachRecoveryCapture(engine);\n },\n };\n}\n\nfunction attachRecoveryCapture(engine: EngineContext): void {\n engine._dlr = {\n u(tex, url, opts) {\n tex._recoverySource = { kind: \"url\", url, opts: { ...opts } };\n },\n s(tex, r, g, b, a) {\n tex._recoverySource = { kind: \"solid\", rgba: [r, g, b, a] };\n },\n b(tex, bitmap, srgb, mipMaps, fallback) {\n tex._recoverySource = {\n kind: \"bitmap\",\n bitmap,\n srgb,\n mipMaps,\n fallback,\n samplerDesc: { magFilter: \"linear\", minFilter: \"linear\", mipmapFilter: \"linear\", addressModeU: \"repeat\", addressModeV: \"repeat\", maxAnisotropy: 4 },\n };\n },\n m(mesh, uv2s, tangents, colors, gpuIndices, indexFormat) {\n mesh._cpuUv2s = uv2s;\n mesh._cpuTangents = tangents;\n mesh._cpuColors = colors;\n mesh._cpuGpuIndices = gpuIndices;\n mesh._cpuIndexFormat = indexFormat;\n },\n };\n}\n\nfunction detachRecoveryCapture(engine: EngineContext): void {\n engine._dlr = undefined;\n}\n\nexport function markNextDeviceLossForRecovery(engine: EngineContext): boolean {\n const state = _states?.get(engine as EngineContext);\n if (!state?.enabled) {\n return false;\n }\n state.forceNextLoss = true;\n return true;\n}\n\nfunction arm(engine: EngineContext, state: RecoveryState): void {\n const device = engine._device;\n if (state.armedDevice === device) {\n return;\n }\n state.armedDevice = device;\n void device.lost.then(async (info) => {\n if (!state.enabled || state.armedDevice !== device) {\n return;\n }\n const forced = state.forceNextLoss;\n state.forceNextLoss = false;\n if (info.reason === \"destroyed\" && !forced) {\n return;\n }\n state.options.onLost?.(info);\n try {\n await recoverDevice(engine, state);\n if (state.enabled) {\n arm(engine, state);\n }\n state.options.onRecovered?.();\n } catch (error) {\n state.options.onRecoveryFailed?.(error);\n }\n });\n}\n\nasync function recoverDevice(engine: EngineContext, state: RecoveryState): Promise<void> {\n if (state.recovering) {\n return;\n }\n state.recovering = true;\n const wasRunning = engine._renderFn !== null;\n stopEngine(engine);\n\n try {\n const adapter = await navigator.gpu.requestAdapter({ powerPreference: \"high-performance\" });\n if (!adapter) {\n throw new Error(\"WebGPU adapter not available during device recovery\");\n }\n const missingFeatures = state.requiredFeatures.filter((f) => !adapter.features.has(f));\n if (missingFeatures.length > 0) {\n throw new Error(`WebGPU device recovery missing required features: ${missingFeatures.join(\", \")}`);\n }\n engine._device = await adapter.requestDevice({ requiredFeatures: state.requiredFeatures });\n // Reconfigure every surface's canvas context against the new device and re-acquire\n // its swapchain texture (the previous device's textures are invalid). The rebuilt\n // frame graphs need fresh color attachments. Per-surface `_swapchainCopySrc` is\n // honoured so surfaces that had been promoted to COPY_SRC for screenshot readback\n // keep that capability across recovery; surfaces that never captured stay\n // RENDER_ATTACHMENT-only.\n for (const surface of engine.surfaces) {\n const usage = surface._swapchainCopySrc ? TU.RENDER_ATTACHMENT | TU.COPY_SRC : TU.RENDER_ATTACHMENT;\n surface._context.configure({\n device: engine._device,\n format: surface._configureFormat,\n alphaMode: surface._alphaMode,\n usage,\n viewFormats: [surface.format],\n });\n _refreshScRT(surface);\n }\n clearSceneBGLCache();\n resizeEngine(engine);\n\n await rebuildRegisteredScenes(engine);\n } finally {\n state.recovering = false;\n }\n\n if (wasRunning) {\n await startEngine(engine);\n }\n}\n\nasync function rebuildRegisteredScenes(engine: EngineContext): Promise<void> {\n for (const surface of engine.surfaces) {\n for (const ctx of surface._renderingContexts) {\n const scene = ctx as SceneContext;\n if (!isRenderingContextRegistered(surface, scene)) {\n continue;\n }\n await rebuildSceneGpu(engine, scene);\n }\n }\n}\n\nasync function rebuildSceneGpu(engine: EngineContext, scene: SceneContext): Promise<void> {\n await rebuildSceneTextures(engine, scene);\n await rebuildMeshes(engine, scene);\n\n scene._renderables.length = 0;\n scene._uniformUpdaters.length = 0;\n scene._meshDisposables.clear();\n scene._meshAuxDisposables.clear();\n if (scene._lightGpuState) {\n scene._lightGpuState = undefined;\n }\n\n for (const [build, meshes] of scene._groups) {\n const result = await build(scene, meshes);\n scene._renderables.push(...result.renderables);\n if (result.updater) {\n scene._uniformUpdaters.push(result.updater);\n }\n }\n scene._renderables.sort((a, b) => a.order - b.order);\n scene._renderableVersion++;\n resetFrameGraphTasks(engine, scene);\n scene._frameGraph.build();\n}\n\nfunction resetFrameGraphTasks(engine: EngineContext, scene: SceneContext): void {\n for (const task of scene._frameGraph._tasks) {\n if (!(\"_sceneUBO\" in task && \"_sceneBG\" in task && \"_opaqueBindings\" in task)) {\n continue;\n }\n const rt = task as unknown as RecoverableRenderTask;\n rt._sceneUBO = createEmptyUniformBuffer(engine, SCENE_UBO_BYTES);\n rt._lightsUBO = ensureSceneLightState(engine, scene)._buffer;\n rt._sceneBG = engine._device.createBindGroup({\n layout: getSceneBindGroupLayout(engine),\n entries: [\n { binding: 0, resource: { buffer: rt._sceneUBO } },\n { binding: 1, resource: { buffer: rt._lightsUBO } },\n ],\n });\n rt._opaqueBindings.length = 0;\n rt._directBindings.length = 0;\n rt._transparentBindings.length = 0;\n rt._opaqueBundles.length = 0;\n rt._lastVersion = -1;\n rt._su.length = 0;\n }\n}\n\nasync function rebuildMeshes(engine: EngineContext, scene: SceneContext): Promise<void> {\n let skeletonFactory: typeof createSkeleton | null = null;\n let morphFactory: typeof createMorphTargets | null = null;\n\n for (const mesh of scene.meshes) {\n if (mesh._cpuPositions && mesh._cpuNormals && mesh._cpuIndices) {\n mesh._gpu = uploadRetainedMesh(engine, mesh);\n }\n if (mesh.skeleton) {\n skeletonFactory ??= (await import(\"../skeleton/create-skeleton.js\")).createSkeleton;\n const old = mesh.skeleton;\n const rebuilt = skeletonFactory(engine, old.joints, old.weights, old.boneCount, old.boneMatrices, old.joints1, old.weights1);\n Object.assign(old as MutableSkeleton, rebuilt);\n }\n if (mesh.morphTargets) {\n morphFactory ??= (await import(\"../morph/create-morph-targets.js\")).createMorphTargets;\n const old = mesh.morphTargets;\n const rebuilt = morphFactory(\n engine,\n old.targets.map((t) => ({ positions: t.positions, normals: t.normals })),\n mesh._cpuPositions ? mesh._cpuPositions.length / 3 : 0,\n Array.from(old.weights)\n );\n Object.assign(old as MutableMorphTargets, rebuilt);\n }\n }\n}\n\nfunction uploadRetainedMesh(engine: EngineContext, mesh: Mesh): MeshGPU {\n const positions = mesh._cpuPositions!;\n const normals = mesh._cpuNormals!;\n const uvs = mesh._cpuUvs;\n const indices = mesh._cpuGpuIndices ?? mesh._cpuIndices!;\n const device = engine._device;\n let uvBuffer: GPUBuffer;\n if (uvs && uvs.length > 0) {\n uvBuffer = createMappedBuffer(engine, uvs, BU.VERTEX);\n } else {\n uvBuffer = device.createBuffer({ size: (positions.length / 3) * 8, usage: BU.VERTEX, mappedAtCreation: true });\n uvBuffer.unmap();\n }\n return {\n positionBuffer: createMappedBuffer(engine, positions, BU.VERTEX),\n normalBuffer: createMappedBuffer(engine, normals, BU.VERTEX),\n tangentBuffer: mesh._cpuTangents ? createMappedBuffer(engine, mesh._cpuTangents, BU.VERTEX) : null,\n uvBuffer,\n uv2Buffer: mesh._cpuUv2s ? createMappedBuffer(engine, mesh._cpuUv2s, BU.VERTEX) : null,\n colorBuffer: mesh._cpuColors ? createMappedBuffer(engine, mesh._cpuColors, BU.VERTEX) : null,\n hasUv: !!uvs && uvs.length > 0,\n hasUv2: !!mesh._cpuUv2s && mesh._cpuUv2s.length > 0,\n hasTangent: !!mesh._cpuTangents && mesh._cpuTangents.length > 0,\n hasColor: !!mesh._cpuColors && mesh._cpuColors.length > 0,\n indexBuffer: createMappedBuffer(engine, indices, BU.INDEX),\n indexCount: mesh._gpu.indexCount,\n indexFormat: mesh._cpuIndexFormat ?? mesh._gpu.indexFormat,\n };\n}\n\nasync function rebuildTexture2D(engine: EngineContext, tex: Texture2D): Promise<void> {\n const source = tex._recoverySource;\n if (!source) {\n return;\n }\n if (source.kind === \"url\") {\n const rebuilt = await rebuildUrlTexture2D(engine, source.url, source.opts);\n tex.texture = rebuilt.texture;\n tex.view = rebuilt.view;\n tex.sampler = rebuilt.sampler;\n tex.width = rebuilt.width;\n tex.height = rebuilt.height;\n tex._recoverySource = source;\n return;\n }\n if (source.kind === \"solid\") {\n const texture = engine._device.createTexture({ size: { width: 1, height: 1 }, format: \"rgba8unorm\", usage: TU.TEXTURE_BINDING | TU.COPY_DST });\n const data = new U8(source.rgba.map((v) => Math.round(v * 255)));\n engine._device.queue.writeTexture({ texture }, data, { bytesPerRow: 4, rowsPerImage: 1 }, { width: 1, height: 1 });\n tex.texture = texture;\n tex.view = texture.createView();\n tex.sampler = getBilinearSampler(engine);\n tex.width = 1;\n tex.height = 1;\n return;\n }\n const width = source.bitmap?.width ?? 1;\n const height = source.bitmap?.height ?? 1;\n const format: GPUTextureFormat = source.srgb ? \"rgba8unorm-srgb\" : \"rgba8unorm\";\n const mipLevelCount = source.mipMaps ? Math.floor(Math.log2(Math.max(width, height))) + 1 : 1;\n const texture = engine._device.createTexture({\n size: { width, height },\n format,\n mipLevelCount,\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.COPY_SRC | TU.RENDER_ATTACHMENT,\n });\n if (source.bitmap) {\n engine._device.queue.copyExternalImageToTexture({ source: source.bitmap }, { texture, premultipliedAlpha: false }, { width, height });\n if (source.mipMaps && mipLevelCount > 1) {\n const { generateMipmaps } = await import(\"../texture/generate-mipmaps.js\");\n generateMipmaps(engine, texture);\n }\n } else {\n engine._device.queue.writeTexture({ texture }, (source.fallback ?? new U8([255, 255, 255, 255])) as Uint8Array<ArrayBuffer>, { bytesPerRow: 4 }, { width: 1, height: 1 });\n }\n tex.texture = texture;\n tex.view = texture.createView();\n tex.sampler = getOrCreateSampler(engine, source.samplerDesc);\n tex.width = width;\n tex.height = height;\n}\n\nasync function rebuildUrlTexture2D(engine: EngineContext, url: string, opts: Texture2DOptions): Promise<Texture2D> {\n const mipMaps = opts.mipMaps ?? true;\n const addressModeU = opts.addressModeU ?? \"repeat\";\n const addressModeV = opts.addressModeV ?? \"repeat\";\n const invertY = opts.invertY ?? true;\n const srgb = opts.srgb ?? false;\n const premultiplyAlpha = opts.premultiplyAlpha ?? false;\n const format: GPUTextureFormat = srgb ? \"rgba8unorm-srgb\" : \"rgba8unorm\";\n\n const response = await fetch(url);\n const blob = await response.blob();\n const imageBitmap = await createImageBitmap(blob, {\n premultiplyAlpha: premultiplyAlpha ? \"premultiply\" : \"none\",\n colorSpaceConversion: \"none\",\n });\n\n const width = imageBitmap.width;\n const height = imageBitmap.height;\n const mipLevelCount = mipMaps ? Math.floor(Math.log2(Math.max(width, height))) + 1 : 1;\n const texture = engine._device.createTexture({\n size: { width, height },\n format,\n mipLevelCount,\n usage: TU.TEXTURE_BINDING | TU.COPY_DST | TU.RENDER_ATTACHMENT,\n });\n engine._device.queue.copyExternalImageToTexture({ source: imageBitmap, flipY: invertY }, { texture, premultipliedAlpha: premultiplyAlpha }, { width, height });\n imageBitmap.close();\n\n if (mipMaps && mipLevelCount > 1) {\n const { generateMipmaps } = await import(\"../texture/generate-mipmaps.js\");\n generateMipmaps(engine, texture);\n }\n\n const minF = opts.minFilter ?? \"linear\";\n const magF = opts.magFilter ?? \"linear\";\n const mipF: GPUMipmapFilterMode = mipMaps ? \"linear\" : \"nearest\";\n const allLinear = minF === \"linear\" && magF === \"linear\" && mipF === \"linear\";\n const sampler = getOrCreateSampler(engine, {\n addressModeU,\n addressModeV,\n minFilter: minF,\n magFilter: magF,\n mipmapFilter: mipF,\n maxAnisotropy: allLinear ? 4 : 1,\n });\n\n return { texture, view: texture.createView(), sampler, width, height };\n}\n\nasync function rebuildSceneTextures(engine: EngineContext, scene: SceneContext): Promise<void> {\n const seen = new Set<Texture2D>();\n const visited = new WeakSet<object>();\n const promises: Promise<void>[] = [];\n const visit = (value: unknown): void => {\n if (!value || typeof value !== \"object\") {\n return;\n }\n const obj = value as Record<string, unknown>;\n if (obj.texture && obj.view && obj.sampler && typeof obj.width === \"number\" && typeof obj.height === \"number\") {\n const tex = obj as unknown as Texture2D;\n if (!seen.has(tex)) {\n seen.add(tex);\n promises.push(rebuildTexture2D(engine, tex));\n }\n return;\n }\n if (visited.has(value)) {\n return;\n }\n visited.add(value);\n for (const child of Object.values(obj)) {\n visit(child);\n }\n };\n for (const mesh of scene.meshes) {\n visit(mesh.material);\n }\n await Promise.all(promises);\n}\n"],"names":["texture"],"mappings":";;;;;;;;;;;AA8DA,IAAI,OAAA,GAAwD,IAAA;AAE5D,SAAS,MAAA,GAAgD;AACrD,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA,OAAA,uBAAc,OAAA,EAAQ;AAAA,EAC1B;AACA,EAAA,OAAO,OAAA;AACX;AAEA,SAAS,SAAS,MAAA,EAAsC;AACpD,EAAA,IAAI,KAAA,GAAQ,MAAA,EAAO,CAAE,GAAA,CAAI,MAAM,CAAA;AAC/B,EAAA,IAAI,CAAC,KAAA,EAAO;AACR,IAAA,KAAA,GAAQ;AAAA,MACJ,OAAA,EAAS,KAAA;AAAA,MACT,UAAA,EAAY,KAAA;AAAA,MACZ,aAAA,EAAe,KAAA;AAAA,MACf,kBAAkB,EAAC;AAAA,MACnB,WAAA,EAAa,IAAA;AAAA,MACb,SAAS;AAAC,KACd;AACA,IAAA,MAAA,EAAO,CAAE,GAAA,CAAI,MAAA,EAAQ,KAAK,CAAA;AAAA,EAC9B;AACA,EAAA,OAAO,KAAA;AACX;AAEO,SAAS,wBAAA,CAAyB,MAAA,EAAuB,OAAA,GAAqC,EAAC,EAA6B;AAC/H,EAAA,MAAM,KAAA,GAAQ,SAAS,MAAM,CAAA;AAC7B,EAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,EAAA,KAAA,CAAM,OAAA,GAAU,OAAA;AAChB,EAAA,KAAA,CAAM,gBAAA,GAAmB,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,QAAQ,QAAQ,CAAA;AAC3D,EAAA,qBAAA,CAAsB,MAAM,CAAA;AAE5B,EAAA,GAAA,CAAI,QAAQ,KAAK,CAAA;AACjB,EAAA,OAAO;AAAA,IACH,OAAA,GAAgB;AACZ,MAAA,KAAA,CAAM,OAAA,GAAU,KAAA;AAChB,MAAA,qBAAA,CAAsB,MAAM,CAAA;AAAA,IAChC;AAAA,GACJ;AACJ;AAEA,SAAS,sBAAsB,MAAA,EAA6B;AACxD,EAAA,MAAA,CAAO,IAAA,GAAO;AAAA,IACV,CAAA,CAAE,GAAA,EAAK,GAAA,EAAK,IAAA,EAAM;AACd,MAAA,GAAA,CAAI,eAAA,GAAkB,EAAE,IAAA,EAAM,KAAA,EAAO,KAAK,IAAA,EAAM,EAAE,GAAG,IAAA,EAAK,EAAE;AAAA,IAChE,CAAA;AAAA,IACA,CAAA,CAAE,GAAA,EAAK,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG;AACf,MAAA,GAAA,CAAI,eAAA,GAAkB,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,EAAE;AAAA,IAC9D,CAAA;AAAA,IACA,CAAA,CAAE,GAAA,EAAK,MAAA,EAAQ,IAAA,EAAM,SAAS,QAAA,EAAU;AACpC,MAAA,GAAA,CAAI,eAAA,GAAkB;AAAA,QAClB,IAAA,EAAM,QAAA;AAAA,QACN,MAAA;AAAA,QACA,IAAA;AAAA,QACA,OAAA;AAAA,QACA,QAAA;AAAA,QACA,WAAA,EAAa,EAAE,SAAA,EAAW,QAAA,EAAU,SAAA,EAAW,QAAA,EAAU,YAAA,EAAc,QAAA,EAAU,YAAA,EAAc,QAAA,EAAU,YAAA,EAAc,QAAA,EAAU,eAAe,CAAA;AAAE,OACtJ;AAAA,IACJ,CAAA;AAAA,IACA,EAAE,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,MAAA,EAAQ,YAAY,WAAA,EAAa;AACrD,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,MAAA,IAAA,CAAK,YAAA,GAAe,QAAA;AACpB,MAAA,IAAA,CAAK,UAAA,GAAa,MAAA;AAClB,MAAA,IAAA,CAAK,cAAA,GAAiB,UAAA;AACtB,MAAA,IAAA,CAAK,eAAA,GAAkB,WAAA;AAAA,IAC3B;AAAA,GACJ;AACJ;AAEA,SAAS,sBAAsB,MAAA,EAA6B;AACxD,EAAA,MAAA,CAAO,IAAA,GAAO,MAAA;AAClB;AAEO,SAAS,8BAA8B,MAAA,EAAgC;AAC1E,EAAA,MAAM,KAAA,GAAQ,OAAA,EAAS,GAAA,CAAI,MAAuB,CAAA;AAClD,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACjB,IAAA,OAAO,KAAA;AAAA,EACX;AACA,EAAA,KAAA,CAAM,aAAA,GAAgB,IAAA;AACtB,EAAA,OAAO,IAAA;AACX;AAEA,SAAS,GAAA,CAAI,QAAuB,KAAA,EAA4B;AAC5D,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AACtB,EAAA,IAAI,KAAA,CAAM,gBAAgB,MAAA,EAAQ;AAC9B,IAAA;AAAA,EACJ;AACA,EAAA,KAAA,CAAM,WAAA,GAAc,MAAA;AACpB,EAAA,KAAK,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,OAAO,IAAA,KAAS;AAClC,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,IAAW,KAAA,CAAM,gBAAgB,MAAA,EAAQ;AAChD,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,SAAS,KAAA,CAAM,aAAA;AACrB,IAAA,KAAA,CAAM,aAAA,GAAgB,KAAA;AACtB,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,WAAA,IAAe,CAAC,MAAA,EAAQ;AACxC,MAAA;AAAA,IACJ;AACA,IAAA,KAAA,CAAM,OAAA,CAAQ,SAAS,IAAI,CAAA;AAC3B,IAAA,IAAI;AACA,MAAA,MAAM,aAAA,CAAc,QAAQ,KAAK,CAAA;AACjC,MAAA,IAAI,MAAM,OAAA,EAAS;AACf,QAAA,GAAA,CAAI,QAAQ,KAAK,CAAA;AAAA,MACrB;AACA,MAAA,KAAA,CAAM,QAAQ,WAAA,IAAc;AAAA,IAChC,SAAS,KAAA,EAAO;AACZ,MAAA,KAAA,CAAM,OAAA,CAAQ,mBAAmB,KAAK,CAAA;AAAA,IAC1C;AAAA,EACJ,CAAC,CAAA;AACL;AAEA,eAAe,aAAA,CAAc,QAAuB,KAAA,EAAqC;AACrF,EAAA,IAAI,MAAM,UAAA,EAAY;AAClB,IAAA;AAAA,EACJ;AACA,EAAA,KAAA,CAAM,UAAA,GAAa,IAAA;AACnB,EAAA,MAAM,UAAA,GAAa,OAAO,SAAA,KAAc,IAAA;AACxC,EAAA,UAAA,CAAW,MAAM,CAAA;AAEjB,EAAA,IAAI;AACA,IAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,GAAA,CAAI,eAAe,EAAE,eAAA,EAAiB,oBAAoB,CAAA;AAC1F,IAAA,IAAI,CAAC,OAAA,EAAS;AACV,MAAA,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAAA,IACzE;AACA,IAAA,MAAM,eAAA,GAAkB,KAAA,CAAM,gBAAA,CAAiB,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,OAAA,CAAQ,QAAA,CAAS,GAAA,CAAI,CAAC,CAAC,CAAA;AACrF,IAAA,IAAI,eAAA,CAAgB,SAAS,CAAA,EAAG;AAC5B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kDAAA,EAAqD,gBAAgB,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,IACrG;AACA,IAAA,MAAA,CAAO,OAAA,GAAU,MAAM,OAAA,CAAQ,aAAA,CAAc,EAAE,gBAAA,EAAkB,KAAA,CAAM,kBAAkB,CAAA;AAOzF,IAAA,KAAA,MAAW,OAAA,IAAW,OAAO,QAAA,EAAU;AACnC,MAAA,MAAM,QAAQ,OAAA,CAAQ,iBAAA,GAAoB,GAAG,iBAAA,GAAoB,EAAA,CAAG,WAAW,EAAA,CAAG,iBAAA;AAClF,MAAA,OAAA,CAAQ,SAAS,SAAA,CAAU;AAAA,QACvB,QAAQ,MAAA,CAAO,OAAA;AAAA,QACf,QAAQ,OAAA,CAAQ,gBAAA;AAAA,QAChB,WAAW,OAAA,CAAQ,UAAA;AAAA,QACnB,KAAA;AAAA,QACA,WAAA,EAAa,CAAC,OAAA,CAAQ,MAAM;AAAA,OAC/B,CAAA;AACD,MAAA,YAAA,CAAa,OAAO,CAAA;AAAA,IACxB;AACA,IAAA,kBAAA,EAAmB;AACnB,IAAA,YAAA,CAAa,MAAM,CAAA;AAEnB,IAAA,MAAM,wBAAwB,MAAM,CAAA;AAAA,EACxC,CAAA,SAAE;AACE,IAAA,KAAA,CAAM,UAAA,GAAa,KAAA;AAAA,EACvB;AAEA,EAAA,IAAI,UAAA,EAAY;AACZ,IAAA,MAAM,YAAY,MAAM,CAAA;AAAA,EAC5B;AACJ;AAEA,eAAe,wBAAwB,MAAA,EAAsC;AACzE,EAAA,KAAA,MAAW,OAAA,IAAW,OAAO,QAAA,EAAU;AACnC,IAAA,KAAA,MAAW,GAAA,IAAO,QAAQ,kBAAA,EAAoB;AAC1C,MAAA,MAAM,KAAA,GAAQ,GAAA;AACd,MAAA,IAAI,CAAC,4BAAA,CAA6B,OAAA,EAAS,KAAK,CAAA,EAAG;AAC/C,QAAA;AAAA,MACJ;AACA,MAAA,MAAM,eAAA,CAAgB,QAAQ,KAAK,CAAA;AAAA,IACvC;AAAA,EACJ;AACJ;AAEA,eAAe,eAAA,CAAgB,QAAuB,KAAA,EAAoC;AACtF,EAAA,MAAM,oBAAA,CAAqB,QAAQ,KAAK,CAAA;AACxC,EAAA,MAAM,aAAA,CAAc,QAAQ,KAAK,CAAA;AAEjC,EAAA,KAAA,CAAM,aAAa,MAAA,GAAS,CAAA;AAC5B,EAAA,KAAA,CAAM,iBAAiB,MAAA,GAAS,CAAA;AAChC,EAAA,KAAA,CAAM,iBAAiB,KAAA,EAAM;AAC7B,EAAA,KAAA,CAAM,oBAAoB,KAAA,EAAM;AAChC,EAAA,IAAI,MAAM,cAAA,EAAgB;AACtB,IAAA,KAAA,CAAM,cAAA,GAAiB,MAAA;AAAA,EAC3B;AAEA,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,MAAM,CAAA,IAAK,MAAM,OAAA,EAAS;AACzC,IAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,KAAA,EAAO,MAAM,CAAA;AACxC,IAAA,KAAA,CAAM,YAAA,CAAa,IAAA,CAAK,GAAG,MAAA,CAAO,WAAW,CAAA;AAC7C,IAAA,IAAI,OAAO,OAAA,EAAS;AAChB,MAAA,KAAA,CAAM,gBAAA,CAAiB,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA;AAAA,IAC9C;AAAA,EACJ;AACA,EAAA,KAAA,CAAM,YAAA,CAAa,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,KAAA,GAAQ,EAAE,KAAK,CAAA;AACnD,EAAA,KAAA,CAAM,kBAAA,EAAA;AACN,EAAA,oBAAA,CAAqB,QAAQ,KAAK,CAAA;AAClC,EAAA,KAAA,CAAM,YAAY,KAAA,EAAM;AAC5B;AAEA,SAAS,oBAAA,CAAqB,QAAuB,KAAA,EAA2B;AAC5E,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,CAAM,WAAA,CAAY,MAAA,EAAQ;AACzC,IAAA,IAAI,EAAE,WAAA,IAAe,IAAA,IAAQ,UAAA,IAAc,IAAA,IAAQ,qBAAqB,IAAA,CAAA,EAAO;AAC3E,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,EAAA,GAAK,IAAA;AACX,IAAA,EAAA,CAAG,SAAA,GAAY,wBAAA,CAAyB,MAAA,EAAQ,eAAe,CAAA;AAC/D,IAAA,EAAA,CAAG,UAAA,GAAa,qBAAA,CAAsB,MAAA,EAAQ,KAAK,CAAA,CAAE,OAAA;AACrD,IAAA,EAAA,CAAG,QAAA,GAAW,MAAA,CAAO,OAAA,CAAQ,eAAA,CAAgB;AAAA,MACzC,MAAA,EAAQ,wBAAwB,MAAM,CAAA;AAAA,MACtC,OAAA,EAAS;AAAA,QACL,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,EAAA,CAAG,WAAU,EAAE;AAAA,QACjD,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,EAAA,CAAG,YAAW;AAAE;AACtD,KACH,CAAA;AACD,IAAA,EAAA,CAAG,gBAAgB,MAAA,GAAS,CAAA;AAC5B,IAAA,EAAA,CAAG,gBAAgB,MAAA,GAAS,CAAA;AAC5B,IAAA,EAAA,CAAG,qBAAqB,MAAA,GAAS,CAAA;AACjC,IAAA,EAAA,CAAG,eAAe,MAAA,GAAS,CAAA;AAC3B,IAAA,EAAA,CAAG,YAAA,GAAe,EAAA;AAClB,IAAA,EAAA,CAAG,IAAI,MAAA,GAAS,CAAA;AAAA,EACpB;AACJ;AAEA,eAAe,aAAA,CAAc,QAAuB,KAAA,EAAoC;AACpF,EAAA,IAAI,eAAA,GAAgD,IAAA;AACpD,EAAA,IAAI,YAAA,GAAiD,IAAA;AAErD,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,MAAA,EAAQ;AAC7B,IAAA,IAAI,IAAA,CAAK,aAAA,IAAiB,IAAA,CAAK,WAAA,IAAe,KAAK,WAAA,EAAa;AAC5D,MAAA,IAAA,CAAK,IAAA,GAAO,kBAAA,CAAmB,MAAA,EAAQ,IAAI,CAAA;AAAA,IAC/C;AACA,IAAA,IAAI,KAAK,QAAA,EAAU;AACf,MAAA,eAAA,KAAA,CAAqB,MAAM,OAAO,gCAAgC,CAAA,EAAG,cAAA;AACrE,MAAA,MAAM,MAAM,IAAA,CAAK,QAAA;AACjB,MAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,MAAA,EAAQ,GAAA,CAAI,QAAQ,GAAA,CAAI,OAAA,EAAS,GAAA,CAAI,SAAA,EAAW,GAAA,CAAI,YAAA,EAAc,GAAA,CAAI,OAAA,EAAS,IAAI,QAAQ,CAAA;AAC3H,MAAA,MAAA,CAAO,MAAA,CAAO,KAAwB,OAAO,CAAA;AAAA,IACjD;AACA,IAAA,IAAI,KAAK,YAAA,EAAc;AACnB,MAAA,YAAA,KAAA,CAAkB,MAAM,OAAO,kCAAkC,CAAA,EAAG,kBAAA;AACpE,MAAA,MAAM,MAAM,IAAA,CAAK,YAAA;AACjB,MAAA,MAAM,OAAA,GAAU,YAAA;AAAA,QACZ,MAAA;AAAA,QACA,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,SAAA,EAAW,CAAA,CAAE,SAAA,EAAW,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ,CAAE,CAAA;AAAA,QACvE,IAAA,CAAK,aAAA,GAAgB,IAAA,CAAK,aAAA,CAAc,SAAS,CAAA,GAAI,CAAA;AAAA,QACrD,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,OAAO;AAAA,OAC1B;AACA,MAAA,MAAA,CAAO,MAAA,CAAO,KAA4B,OAAO,CAAA;AAAA,IACrD;AAAA,EACJ;AACJ;AAEA,SAAS,kBAAA,CAAmB,QAAuB,IAAA,EAAqB;AACpE,EAAA,MAAM,YAAY,IAAA,CAAK,aAAA;AACvB,EAAA,MAAM,UAAU,IAAA,CAAK,WAAA;AACrB,EAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,cAAA,IAAkB,IAAA,CAAK,WAAA;AAC5C,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AACtB,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,GAAA,IAAO,GAAA,CAAI,MAAA,GAAS,CAAA,EAAG;AACvB,IAAA,QAAA,GAAW,kBAAA,CAAmB,MAAA,EAAQ,GAAA,EAAK,EAAA,CAAG,MAAM,CAAA;AAAA,EACxD,CAAA,MAAO;AACH,IAAA,QAAA,GAAW,MAAA,CAAO,YAAA,CAAa,EAAE,IAAA,EAAO,SAAA,CAAU,MAAA,GAAS,CAAA,GAAK,CAAA,EAAG,KAAA,EAAO,EAAA,CAAG,MAAA,EAAQ,gBAAA,EAAkB,MAAM,CAAA;AAC7G,IAAA,QAAA,CAAS,KAAA,EAAM;AAAA,EACnB;AACA,EAAA,OAAO;AAAA,IACH,cAAA,EAAgB,kBAAA,CAAmB,MAAA,EAAQ,SAAA,EAAW,GAAG,MAAM,CAAA;AAAA,IAC/D,YAAA,EAAc,kBAAA,CAAmB,MAAA,EAAQ,OAAA,EAAS,GAAG,MAAM,CAAA;AAAA,IAC3D,aAAA,EAAe,KAAK,YAAA,GAAe,kBAAA,CAAmB,QAAQ,IAAA,CAAK,YAAA,EAAc,EAAA,CAAG,MAAM,CAAA,GAAI,IAAA;AAAA,IAC9F,QAAA;AAAA,IACA,SAAA,EAAW,KAAK,QAAA,GAAW,kBAAA,CAAmB,QAAQ,IAAA,CAAK,QAAA,EAAU,EAAA,CAAG,MAAM,CAAA,GAAI,IAAA;AAAA,IAClF,WAAA,EAAa,KAAK,UAAA,GAAa,kBAAA,CAAmB,QAAQ,IAAA,CAAK,UAAA,EAAY,EAAA,CAAG,MAAM,CAAA,GAAI,IAAA;AAAA,IACxF,KAAA,EAAO,CAAC,CAAC,GAAA,IAAO,IAAI,MAAA,GAAS,CAAA;AAAA,IAC7B,QAAQ,CAAC,CAAC,KAAK,QAAA,IAAY,IAAA,CAAK,SAAS,MAAA,GAAS,CAAA;AAAA,IAClD,YAAY,CAAC,CAAC,KAAK,YAAA,IAAgB,IAAA,CAAK,aAAa,MAAA,GAAS,CAAA;AAAA,IAC9D,UAAU,CAAC,CAAC,KAAK,UAAA,IAAc,IAAA,CAAK,WAAW,MAAA,GAAS,CAAA;AAAA,IACxD,WAAA,EAAa,kBAAA,CAAmB,MAAA,EAAQ,OAAA,EAAS,GAAG,KAAK,CAAA;AAAA,IACzD,UAAA,EAAY,KAAK,IAAA,CAAK,UAAA;AAAA,IACtB,WAAA,EAAa,IAAA,CAAK,eAAA,IAAmB,IAAA,CAAK,IAAA,CAAK;AAAA,GACnD;AACJ;AAEA,eAAe,gBAAA,CAAiB,QAAuB,GAAA,EAA+B;AAClF,EAAA,MAAM,SAAS,GAAA,CAAI,eAAA;AACnB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACT,IAAA;AAAA,EACJ;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,KAAA,EAAO;AACvB,IAAA,MAAM,UAAU,MAAM,mBAAA,CAAoB,QAAQ,MAAA,CAAO,GAAA,EAAK,OAAO,IAAI,CAAA;AACzE,IAAA,GAAA,CAAI,UAAU,OAAA,CAAQ,OAAA;AACtB,IAAA,GAAA,CAAI,OAAO,OAAA,CAAQ,IAAA;AACnB,IAAA,GAAA,CAAI,UAAU,OAAA,CAAQ,OAAA;AACtB,IAAA,GAAA,CAAI,QAAQ,OAAA,CAAQ,KAAA;AACpB,IAAA,GAAA,CAAI,SAAS,OAAA,CAAQ,MAAA;AACrB,IAAA,GAAA,CAAI,eAAA,GAAkB,MAAA;AACtB,IAAA;AAAA,EACJ;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,OAAA,EAAS;AACzB,IAAA,MAAMA,WAAU,MAAA,CAAO,OAAA,CAAQ,cAAc,EAAE,IAAA,EAAM,EAAE,KAAA,EAAO,CAAA,EAAG,QAAQ,CAAA,EAAE,EAAG,QAAQ,YAAA,EAAc,KAAA,EAAO,GAAG,eAAA,GAAkB,EAAA,CAAG,UAAU,CAAA;AAC7I,IAAA,MAAM,IAAA,GAAO,IAAI,EAAA,CAAG,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,GAAG,CAAC,CAAC,CAAA;AAC/D,IAAA,MAAA,CAAO,QAAQ,KAAA,CAAM,YAAA,CAAa,EAAE,OAAA,EAAAA,QAAAA,IAAW,IAAA,EAAM,EAAE,aAAa,CAAA,EAAG,YAAA,EAAc,GAAE,EAAG,EAAE,OAAO,CAAA,EAAG,MAAA,EAAQ,GAAG,CAAA;AACjH,IAAA,GAAA,CAAI,OAAA,GAAUA,QAAAA;AACd,IAAA,GAAA,CAAI,IAAA,GAAOA,SAAQ,UAAA,EAAW;AAC9B,IAAA,GAAA,CAAI,OAAA,GAAU,mBAAmB,MAAM,CAAA;AACvC,IAAA,GAAA,CAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,GAAA,CAAI,MAAA,GAAS,CAAA;AACb,IAAA;AAAA,EACJ;AACA,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,MAAA,EAAQ,KAAA,IAAS,CAAA;AACtC,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,EAAQ,MAAA,IAAU,CAAA;AACxC,EAAA,MAAM,MAAA,GAA2B,MAAA,CAAO,IAAA,GAAO,iBAAA,GAAoB,YAAA;AACnE,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,OAAA,GAAU,IAAA,CAAK,MAAM,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,MAAM,CAAC,CAAC,IAAI,CAAA,GAAI,CAAA;AAC5F,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,aAAA,CAAc;AAAA,IACzC,IAAA,EAAM,EAAE,KAAA,EAAO,MAAA,EAAO;AAAA,IACtB,MAAA;AAAA,IACA,aAAA;AAAA,IACA,OAAO,EAAA,CAAG,eAAA,GAAkB,GAAG,QAAA,GAAW,EAAA,CAAG,WAAW,EAAA,CAAG;AAAA,GAC9D,CAAA;AACD,EAAA,IAAI,OAAO,MAAA,EAAQ;AACf,IAAA,MAAA,CAAO,QAAQ,KAAA,CAAM,0BAAA,CAA2B,EAAE,MAAA,EAAQ,OAAO,MAAA,EAAO,EAAG,EAAE,OAAA,EAAS,oBAAoB,KAAA,EAAM,EAAG,EAAE,KAAA,EAAO,QAAQ,CAAA;AACpI,IAAA,IAAI,MAAA,CAAO,OAAA,IAAW,aAAA,GAAgB,CAAA,EAAG;AACrC,MAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,MAAM,OAAO,gCAAgC,CAAA;AACzE,MAAA,eAAA,CAAgB,QAAQ,OAAO,CAAA;AAAA,IACnC;AAAA,EACJ,CAAA,MAAO;AACH,IAAA,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,YAAA,CAAa,EAAE,OAAA,EAAQ,EAAI,MAAA,CAAO,QAAA,IAAY,IAAI,EAAA,CAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAC,CAAA,EAA+B,EAAE,WAAA,EAAa,CAAA,EAAE,EAAG,EAAE,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAG,CAAA;AAAA,EAC5K;AACA,EAAA,GAAA,CAAI,OAAA,GAAU,OAAA;AACd,EAAA,GAAA,CAAI,IAAA,GAAO,QAAQ,UAAA,EAAW;AAC9B,EAAA,GAAA,CAAI,OAAA,GAAU,kBAAA,CAAmB,MAAA,EAAQ,MAAA,CAAO,WAAW,CAAA;AAC3D,EAAA,GAAA,CAAI,KAAA,GAAQ,KAAA;AACZ,EAAA,GAAA,CAAI,MAAA,GAAS,MAAA;AACjB;AAEA,eAAe,mBAAA,CAAoB,MAAA,EAAuB,GAAA,EAAa,IAAA,EAA4C;AAC/G,EAAA,MAAM,OAAA,GAAU,KAAK,OAAA,IAAW,IAAA;AAChC,EAAA,MAAM,YAAA,GAAe,KAAK,YAAA,IAAgB,QAAA;AAC1C,EAAA,MAAM,YAAA,GAAe,KAAK,YAAA,IAAgB,QAAA;AAC1C,EAAA,MAAM,OAAA,GAAU,KAAK,OAAA,IAAW,IAAA;AAChC,EAAA,MAAM,IAAA,GAAO,KAAK,IAAA,IAAQ,KAAA;AAC1B,EAAA,MAAM,gBAAA,GAAmB,KAAK,gBAAA,IAAoB,KAAA;AAClD,EAAA,MAAM,MAAA,GAA2B,OAAO,iBAAA,GAAoB,YAAA;AAE5D,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAG,CAAA;AAChC,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,EAAA,MAAM,WAAA,GAAc,MAAM,iBAAA,CAAkB,IAAA,EAAM;AAAA,IAC9C,gBAAA,EAAkB,mBAAmB,aAAA,GAAgB,MAAA;AAAA,IACrD,oBAAA,EAAsB;AAAA,GACzB,CAAA;AAED,EAAA,MAAM,QAAQ,WAAA,CAAY,KAAA;AAC1B,EAAA,MAAM,SAAS,WAAA,CAAY,MAAA;AAC3B,EAAA,MAAM,aAAA,GAAgB,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,MAAM,CAAC,CAAC,IAAI,CAAA,GAAI,CAAA;AACrF,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,aAAA,CAAc;AAAA,IACzC,IAAA,EAAM,EAAE,KAAA,EAAO,MAAA,EAAO;AAAA,IACtB,MAAA;AAAA,IACA,aAAA;AAAA,IACA,KAAA,EAAO,EAAA,CAAG,eAAA,GAAkB,EAAA,CAAG,WAAW,EAAA,CAAG;AAAA,GAChD,CAAA;AACD,EAAA,MAAA,CAAO,QAAQ,KAAA,CAAM,0BAAA,CAA2B,EAAE,MAAA,EAAQ,aAAa,KAAA,EAAO,OAAA,EAAQ,EAAG,EAAE,SAAS,kBAAA,EAAoB,gBAAA,IAAoB,EAAE,KAAA,EAAO,QAAQ,CAAA;AAC7J,EAAA,WAAA,CAAY,KAAA,EAAM;AAElB,EAAA,IAAI,OAAA,IAAW,gBAAgB,CAAA,EAAG;AAC9B,IAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,MAAM,OAAO,gCAAgC,CAAA;AACzE,IAAA,eAAA,CAAgB,QAAQ,OAAO,CAAA;AAAA,EACnC;AAEA,EAAA,MAAM,IAAA,GAAO,KAAK,SAAA,IAAa,QAAA;AAC/B,EAAA,MAAM,IAAA,GAAO,KAAK,SAAA,IAAa,QAAA;AAC/B,EAAA,MAAM,IAAA,GAA4B,UAAU,QAAA,GAAW,SAAA;AACvD,EAAA,MAAM,SAAA,GAAY,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,YAAY,IAAA,KAAS,QAAA;AACrE,EAAA,MAAM,OAAA,GAAU,mBAAmB,MAAA,EAAQ;AAAA,IACvC,YAAA;AAAA,IACA,YAAA;AAAA,IACA,SAAA,EAAW,IAAA;AAAA,IACX,SAAA,EAAW,IAAA;AAAA,IACX,YAAA,EAAc,IAAA;AAAA,IACd,aAAA,EAAe,YAAY,CAAA,GAAI;AAAA,GAClC,CAAA;AAED,EAAA,OAAO,EAAE,SAAS,IAAA,EAAM,OAAA,CAAQ,YAAW,EAAG,OAAA,EAAS,OAAO,MAAA,EAAO;AACzE;AAEA,eAAe,oBAAA,CAAqB,QAAuB,KAAA,EAAoC;AAC3F,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAe;AAChC,EAAA,MAAM,OAAA,uBAAc,OAAA,EAAgB;AACpC,EAAA,MAAM,WAA4B,EAAC;AACnC,EAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,KAAyB;AACpC,IAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACrC,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,GAAA,GAAM,KAAA;AACZ,IAAA,IAAI,GAAA,CAAI,OAAA,IAAW,GAAA,CAAI,IAAA,IAAQ,GAAA,CAAI,OAAA,IAAW,OAAO,GAAA,CAAI,KAAA,KAAU,QAAA,IAAY,OAAO,GAAA,CAAI,WAAW,QAAA,EAAU;AAC3G,MAAA,MAAM,GAAA,GAAM,GAAA;AACZ,MAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AAChB,QAAA,IAAA,CAAK,IAAI,GAAG,CAAA;AACZ,QAAA,QAAA,CAAS,IAAA,CAAK,gBAAA,CAAiB,MAAA,EAAQ,GAAG,CAAC,CAAA;AAAA,MAC/C;AACA,MAAA;AAAA,IACJ;AACA,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AACpB,MAAA;AAAA,IACJ;AACA,IAAA,OAAA,CAAQ,IAAI,KAAK,CAAA;AACjB,IAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA,EAAG;AACpC,MAAA,KAAA,CAAM,KAAK,CAAA;AAAA,IACf;AAAA,EACJ,CAAA;AACA,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,MAAA,EAAQ;AAC7B,IAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,EACvB;AACA,EAAA,MAAM,OAAA,CAAQ,IAAI,QAAQ,CAAA;AAC9B;;;;"}
|
package/lib/engine/engine.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { _setHpmAllocator } from '../math/_matrix-allocator.js';
|
|
2
2
|
import { isDomCanvas, _buildSurface, resizeSurface, _refreshScRT, setSurfaceSize } from './surface.js';
|
|
3
3
|
|
|
4
|
-
const VERSION = /* @__PURE__ */ (() => "1.
|
|
4
|
+
const VERSION = /* @__PURE__ */ (() => "1.8.0" )();
|
|
5
5
|
let _vis = 0;
|
|
6
6
|
function bumpVisibilityEpoch() {
|
|
7
7
|
_vis = _vis + 1 | 0;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function createNullEngine(_options) {
|
|
2
|
+
const engine = {
|
|
3
|
+
useHighPrecisionMatrix: false,
|
|
4
|
+
useFloatingOrigin: false,
|
|
5
|
+
drawCallCount: 0,
|
|
6
|
+
gpuFrameTimeMs: 0,
|
|
7
|
+
_animFrameId: 0,
|
|
8
|
+
_renderFn: null,
|
|
9
|
+
_currentDelta: 0,
|
|
10
|
+
_cbs: []
|
|
11
|
+
};
|
|
12
|
+
engine.engine = engine;
|
|
13
|
+
const surfaces = [engine];
|
|
14
|
+
engine.surfaces = surfaces;
|
|
15
|
+
engine._surfaces = surfaces;
|
|
16
|
+
return engine;
|
|
17
|
+
}
|
|
18
|
+
function stepScene(engine, scene, deltaMs) {
|
|
19
|
+
engine._currentDelta = deltaMs;
|
|
20
|
+
scene._update();
|
|
21
|
+
}
|
|
22
|
+
function runHeadlessSteps(engine, scene, steps, deltaMs = 1e3 / 60) {
|
|
23
|
+
for (let i = 0; i < steps; i++) {
|
|
24
|
+
stepScene(engine, scene, deltaMs);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { createNullEngine, runHeadlessSteps, stepScene };
|
|
29
|
+
//# sourceMappingURL=null-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"null-engine.js","sources":["../../../src/engine/null-engine.ts"],"sourcesContent":["import type { EngineContext } from \"./engine.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\n\n/**\n * Options for {@link createNullEngine}.\n */\nexport interface NullEngineOptions {\n /**\n * Reserved for future headless-driver options (e.g. variable-timestep control). No options are\n * consumed today; the property exists only to keep the option-bag shape stable and forbids\n * passing unknown fields.\n */\n reserved?: never;\n}\n\n/**\n * Create a **null engine** — a device-less, surface-less {@link EngineContext} that runs the\n * simulation half of Babylon Lite (physics stepping, animation evaluation, `onBeforeRender`\n * callbacks, transform updates) **without any GPU device or canvas**.\n *\n * This is the Babylon Lite analogue of Babylon.js `NullEngine`: it lets a scene be driven\n * headlessly on a server (plain Node, Deno, a Web Worker, a CI job) so you can run e.g. a Havok\n * physics simulation and read back body transforms with zero rendering.\n *\n * ### What works\n * - `createSceneContext(engine, { defaultRenderTask: false })` — a scene with **no** frame-graph\n * render task (so no swapchain / GPU resources are ever built).\n * - `onBeforeRender(scene, cb)` callbacks (physics `createHavokWorld` registers its step this way).\n * - `stepScene(engine, scene, deltaMs)` to advance one fixed step (replaces the browser\n * `requestAnimationFrame` loop that `startEngine` uses).\n * - Physics with **primitive** collider shapes (box/sphere/capsule/cylinder) whose geometry is\n * given explicitly or derived from `mesh.boundMin`/`boundMax`.\n *\n * ### What is NOT supported (throws or is undefined behaviour)\n * - Any rendering: `startEngine`, `renderFrame`, `captureScreenshot`, adding meshes **with\n * materials** (their deferred GPU builders dereference the absent `_device`), surfaces, RTTs.\n * - Mesh/convex-hull colliders that require `node.worldMatrix` (needs the render-side world-matrix\n * pass). This is a follow-up.\n * - High-precision / floating-origin matrices (they need the F64 allocator that `createEngine`\n * installs). This is a follow-up.\n *\n * @remarks\n * The returned object is deliberately a **partial** {@link EngineContext}: only the fields the\n * device-less simulation/update path reads are populated (`_device` is intentionally absent). The\n * single localized cast below is the whole cost of not yet splitting `EngineContext` from its\n * mandatory `_device`/`SurfaceContext` members — a larger, separate refactor. Every rendering code\n * path is unreachable on a null engine, so the missing GPU fields are never dereferenced.\n *\n * @example\n * ```ts\n * import { createNullEngine, stepScene } from \"babylon-lite\";\n * import { createSceneContext, onBeforeRender } from \"babylon-lite\";\n *\n * const engine = createNullEngine();\n * const scene = createSceneContext(engine, { defaultRenderTask: false });\n *\n * // e.g. real Havok physics — createHavokWorld registers its step via onBeforeRender\n * // const world = createHavokWorld(scene, await HavokPhysics());\n *\n * const stepMs = 1000 / 60;\n * for (let i = 0; i < 180; i++) stepScene(engine, scene, stepMs); // 3s, no rendering\n * ```\n */\nexport function createNullEngine(_options?: NullEngineOptions): EngineContext {\n // Populate only the fields the device-less simulation + update loop reads. GPU/surface\n // members (`_device`, `_context`, `scRT`, `canvas`, `format`, …) are intentionally omitted:\n // the null engine never enters a rendering code path, so they are never dereferenced.\n const engine: Partial<EngineContext> = {\n useHighPrecisionMatrix: false,\n useFloatingOrigin: false,\n drawCallCount: 0,\n gpuFrameTimeMs: 0,\n _animFrameId: 0,\n _renderFn: null,\n _currentDelta: 0,\n _cbs: [],\n };\n // The engine IS its own primary surface (EngineContext extends SurfaceContext), matching the\n // real `createEngine` self-reference — scene binding reads `surface.engine`. `engine` and\n // `surfaces` are `readonly` on the public type, so we write them through a mutable view (the\n // same technique `createEngine` uses to seed the self-referential primary surface).\n (engine as { engine: EngineContext }).engine = engine as EngineContext;\n const surfaces = [engine as EngineContext] as [EngineContext];\n (engine as { surfaces: unknown }).surfaces = surfaces;\n engine._surfaces = surfaces;\n return engine as EngineContext;\n}\n\n/**\n * Advance one fixed simulation step of a headless scene created against a {@link createNullEngine}\n * engine. This is the server-side replacement for the `requestAnimationFrame` loop that\n * `startEngine` runs in the browser.\n *\n * It sets the frame delta and runs the scene's per-frame update, which fires all\n * `onBeforeRender(scene, …)` callbacks (physics step, animation evaluation, user logic). It does\n * **not** record or submit any GPU work.\n *\n * @param engine - A null engine from {@link createNullEngine}.\n * @param scene - A scene created with `createSceneContext(engine, { defaultRenderTask: false })`.\n * @param deltaMs - The fixed timestep for this step, in milliseconds (e.g. `1000 / 60`).\n */\nexport function stepScene(engine: EngineContext, scene: SceneContext, deltaMs: number): void {\n engine._currentDelta = deltaMs;\n scene._update();\n}\n\n/**\n * Convenience driver: advance a headless scene by a fixed number of steps at a fixed timestep.\n * Equivalent to calling {@link stepScene} `steps` times.\n *\n * @param engine - A null engine from {@link createNullEngine}.\n * @param scene - A scene created with `createSceneContext(engine, { defaultRenderTask: false })`.\n * @param steps - Number of fixed steps to advance.\n * @param deltaMs - The fixed timestep per step, in milliseconds (default `1000 / 60`).\n */\nexport function runHeadlessSteps(engine: EngineContext, scene: SceneContext, steps: number, deltaMs = 1000 / 60): void {\n for (let i = 0; i < steps; i++) {\n stepScene(engine, scene, deltaMs);\n }\n}\n"],"names":[],"mappings":"AA+DO,SAAS,iBAAiB,QAAA,EAA6C;AAI1E,EAAA,MAAM,MAAA,GAAiC;AAAA,IACnC,sBAAA,EAAwB,KAAA;AAAA,IACxB,iBAAA,EAAmB,KAAA;AAAA,IACnB,aAAA,EAAe,CAAA;AAAA,IACf,cAAA,EAAgB,CAAA;AAAA,IAChB,YAAA,EAAc,CAAA;AAAA,IACd,SAAA,EAAW,IAAA;AAAA,IACX,aAAA,EAAe,CAAA;AAAA,IACf,MAAM;AAAC,GACX;AAKA,EAAC,OAAqC,MAAA,GAAS,MAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,CAAC,MAAuB,CAAA;AACzC,EAAC,OAAiC,QAAA,GAAW,QAAA;AAC7C,EAAA,MAAA,CAAO,SAAA,GAAY,QAAA;AACnB,EAAA,OAAO,MAAA;AACX;AAeO,SAAS,SAAA,CAAU,MAAA,EAAuB,KAAA,EAAqB,OAAA,EAAuB;AACzF,EAAA,MAAA,CAAO,aAAA,GAAgB,OAAA;AACvB,EAAA,KAAA,CAAM,OAAA,EAAQ;AAClB;AAWO,SAAS,iBAAiB,MAAA,EAAuB,KAAA,EAAqB,KAAA,EAAe,OAAA,GAAU,MAAO,EAAA,EAAU;AACnH,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,CAAA,EAAA,EAAK;AAC5B,IAAA,SAAA,CAAU,MAAA,EAAQ,OAAO,OAAO,CAAA;AAAA,EACpC;AACJ;;;;"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { SS, TU } from '../engine/gpu-flags.js';
|
|
2
|
+
import { getOrCreateSampler, releaseTexture, acquireTexture } from '../resource/gpu-pool.js';
|
|
3
|
+
|
|
4
|
+
function mipLevelCount(width, height) {
|
|
5
|
+
return Math.floor(Math.log2(Math.max(width, height))) + 1;
|
|
6
|
+
}
|
|
7
|
+
const COPY_SHADER = `@group(0)@binding(0)var src:texture_depth_2d;
|
|
8
|
+
struct V{@builtin(position)p:vec4f};
|
|
9
|
+
@vertex fn vs(@builtin(vertex_index)i:u32)->V{let p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3))[i];return V(vec4f(p,0,1));}
|
|
10
|
+
@fragment fn fs(@builtin(position)fc:vec4f)->@location(0)f32{return textureLoad(src,vec2<i32>(fc.xy),0);}`;
|
|
11
|
+
function reduceShader(op) {
|
|
12
|
+
return `@group(0)@binding(0)var src:texture_2d<f32>;
|
|
13
|
+
struct V{@builtin(position)p:vec4f};
|
|
14
|
+
@vertex fn vs(@builtin(vertex_index)i:u32)->V{let p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3))[i];return V(vec4f(p,0,1));}
|
|
15
|
+
@fragment fn fs(@builtin(position)fc:vec4f)->@location(0)f32{
|
|
16
|
+
let c=vec2<i32>(fc.xy)*2;
|
|
17
|
+
let d=vec2<i32>(textureDimensions(src))-vec2<i32>(1,1);
|
|
18
|
+
let x1=min(c.x+1,d.x); let y1=min(c.y+1,d.y);
|
|
19
|
+
let a=textureLoad(src,vec2<i32>(c.x,c.y),0).r;
|
|
20
|
+
let b=textureLoad(src,vec2<i32>(x1,c.y),0).r;
|
|
21
|
+
let e=textureLoad(src,vec2<i32>(c.x,y1),0).r;
|
|
22
|
+
let f=textureLoad(src,vec2<i32>(x1,y1),0).r;
|
|
23
|
+
return ${op}(${op}(a,b),${op}(e,f));
|
|
24
|
+
}`;
|
|
25
|
+
}
|
|
26
|
+
function createDepthPyramid(engine, opts) {
|
|
27
|
+
const device = engine._device;
|
|
28
|
+
const reduce = opts.reduce ?? "max";
|
|
29
|
+
const sampler = getOrCreateSampler(engine, { minFilter: "nearest", magFilter: "nearest", addressModeU: "clamp-to-edge", addressModeV: "clamp-to-edge" });
|
|
30
|
+
const copyBGL = device.createBindGroupLayout({
|
|
31
|
+
entries: [{ binding: 0, visibility: SS.FRAGMENT, texture: { sampleType: "depth", viewDimension: "2d" } }]
|
|
32
|
+
});
|
|
33
|
+
const reduceBGL = device.createBindGroupLayout({
|
|
34
|
+
entries: [{ binding: 0, visibility: SS.FRAGMENT, texture: { sampleType: "unfilterable-float", viewDimension: "2d" } }]
|
|
35
|
+
});
|
|
36
|
+
const mk = (code, layout) => device.createRenderPipeline({
|
|
37
|
+
layout: device.createPipelineLayout({ bindGroupLayouts: [layout] }),
|
|
38
|
+
vertex: { module: device.createShaderModule({ code }), entryPoint: "vs" },
|
|
39
|
+
fragment: { module: device.createShaderModule({ code }), entryPoint: "fs", targets: [{ format: "r32float" }] },
|
|
40
|
+
primitive: { topology: "triangle-list" }
|
|
41
|
+
});
|
|
42
|
+
const copyPipeline = mk(COPY_SHADER, copyBGL);
|
|
43
|
+
const reducePipeline = mk(reduceShader(reduce), reduceBGL);
|
|
44
|
+
let w = Math.max(1, opts.width | 0);
|
|
45
|
+
let h = Math.max(1, opts.height | 0);
|
|
46
|
+
let mips = mipLevelCount(w, h);
|
|
47
|
+
function makeTexture() {
|
|
48
|
+
return device.createTexture({
|
|
49
|
+
label: "depth-pyramid",
|
|
50
|
+
size: { width: w, height: h },
|
|
51
|
+
format: "r32float",
|
|
52
|
+
usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,
|
|
53
|
+
mipLevelCount: mips
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function makeWrapper(tex) {
|
|
57
|
+
const wr = { texture: tex, view: tex.createView(), sampler, width: w, height: h, _sampleType: "float" };
|
|
58
|
+
acquireTexture(wr);
|
|
59
|
+
return wr;
|
|
60
|
+
}
|
|
61
|
+
let gpuTex = makeTexture();
|
|
62
|
+
let wrapper = makeWrapper(gpuTex);
|
|
63
|
+
let copyDstView;
|
|
64
|
+
let reduceLevels = [];
|
|
65
|
+
let copyBindGroup = null;
|
|
66
|
+
let copyBindGroupSource = null;
|
|
67
|
+
function rebuildViews() {
|
|
68
|
+
copyDstView = gpuTex.createView({ baseMipLevel: 0, mipLevelCount: 1 });
|
|
69
|
+
reduceLevels = [];
|
|
70
|
+
for (let mip = 1; mip < mips; mip++) {
|
|
71
|
+
const src = gpuTex.createView({ baseMipLevel: mip - 1, mipLevelCount: 1 });
|
|
72
|
+
const dst = gpuTex.createView({ baseMipLevel: mip, mipLevelCount: 1 });
|
|
73
|
+
reduceLevels.push({ dst, bindGroup: device.createBindGroup({ layout: reduceBGL, entries: [{ binding: 0, resource: src }] }) });
|
|
74
|
+
}
|
|
75
|
+
copyBindGroup = null;
|
|
76
|
+
copyBindGroupSource = null;
|
|
77
|
+
}
|
|
78
|
+
rebuildViews();
|
|
79
|
+
return {
|
|
80
|
+
get texture() {
|
|
81
|
+
return wrapper;
|
|
82
|
+
},
|
|
83
|
+
get mipCount() {
|
|
84
|
+
return mips;
|
|
85
|
+
},
|
|
86
|
+
build(depthTexture, encoder) {
|
|
87
|
+
const enc = encoder ?? device.createCommandEncoder();
|
|
88
|
+
if (copyBindGroup === null || copyBindGroupSource !== depthTexture) {
|
|
89
|
+
copyBindGroup = device.createBindGroup({ layout: copyBGL, entries: [{ binding: 0, resource: depthTexture.view }] });
|
|
90
|
+
copyBindGroupSource = depthTexture;
|
|
91
|
+
}
|
|
92
|
+
const copyPass = enc.beginRenderPass({
|
|
93
|
+
label: "depth-pyramid-copy",
|
|
94
|
+
colorAttachments: [{ view: copyDstView, loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
|
|
95
|
+
});
|
|
96
|
+
copyPass.setPipeline(copyPipeline);
|
|
97
|
+
copyPass.setBindGroup(0, copyBindGroup);
|
|
98
|
+
copyPass.draw(3);
|
|
99
|
+
copyPass.end();
|
|
100
|
+
for (const level of reduceLevels) {
|
|
101
|
+
const pass = enc.beginRenderPass({
|
|
102
|
+
label: "depth-pyramid-reduce",
|
|
103
|
+
colorAttachments: [{ view: level.dst, loadOp: "clear", storeOp: "store", clearValue: { r: 0, g: 0, b: 0, a: 0 } }]
|
|
104
|
+
});
|
|
105
|
+
pass.setPipeline(reducePipeline);
|
|
106
|
+
pass.setBindGroup(0, level.bindGroup);
|
|
107
|
+
pass.draw(3);
|
|
108
|
+
pass.end();
|
|
109
|
+
}
|
|
110
|
+
if (!encoder) {
|
|
111
|
+
device.queue.submit([enc.finish()]);
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
resize(nw, nh) {
|
|
115
|
+
const cw = Math.max(1, nw | 0);
|
|
116
|
+
const ch = Math.max(1, nh | 0);
|
|
117
|
+
if (cw === w && ch === h) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
w = cw;
|
|
121
|
+
h = ch;
|
|
122
|
+
mips = mipLevelCount(w, h);
|
|
123
|
+
const old = wrapper;
|
|
124
|
+
gpuTex = makeTexture();
|
|
125
|
+
wrapper = makeWrapper(gpuTex);
|
|
126
|
+
rebuildViews();
|
|
127
|
+
releaseTexture(old);
|
|
128
|
+
},
|
|
129
|
+
dispose() {
|
|
130
|
+
releaseTexture(wrapper);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function createDepthPyramidTask(engine, scene, opts) {
|
|
135
|
+
const { pyramid, source } = opts;
|
|
136
|
+
return {
|
|
137
|
+
name: "depth-pyramid",
|
|
138
|
+
engine,
|
|
139
|
+
scene,
|
|
140
|
+
_passes: [],
|
|
141
|
+
record() {
|
|
142
|
+
},
|
|
143
|
+
execute() {
|
|
144
|
+
const src = source();
|
|
145
|
+
if (!src) {
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
148
|
+
pyramid.build(src, engine._currentEncoder);
|
|
149
|
+
return pyramid.mipCount;
|
|
150
|
+
},
|
|
151
|
+
dispose() {
|
|
152
|
+
pyramid.dispose();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export { createDepthPyramid, createDepthPyramidTask };
|
|
158
|
+
//# sourceMappingURL=depth-pyramid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"depth-pyramid.js","sources":["../../../src/frame-graph/depth-pyramid.ts"],"sourcesContent":["/**\n * Depth pyramid — a hierarchical (\"Hi-Z\") mip chain of a depth buffer where each coarser level combines its\n * four child texels with `min()` or `max()`. The classic uses are GPU occlusion culling (test a screen-space\n * bounding box against the coarse level that covers it) and hierarchical screen-space ray marching (skip empty\n * space at coarse mips, refine to a precise hit at level 0), plus horizon-search AO and contact shadows.\n *\n * WebGPU has no built-in min/max mip reduction, so — like `generate-mipmaps` — we render a fullscreen triangle\n * per level. Two pipelines:\n * • COPY: sample the source `texture_depth_2d` → write its NDC depth into mip 0 of an `r32float` texture.\n * • REDUCE: each coarser level = `min`/`max` of its four child texels of the previous level.\n *\n * The `reduce` mode is the caller's choice of depth convention + use: a reverse-Z Hi-Z (near = 1) wants `max`\n * (keeps the NEAREST surface per tile — what a skip-empty ray march needs); a farthest-occluder pyramid for\n * occlusion culling wants `min` in reverse-Z (the deepest occluder is the conservative bound). Nearest sampler,\n * so the consumer reads it with `textureLoad(tex, coord, mip)`.\n *\n * The output `Texture2D` ref-counts through the shared texture pool: the pyramid holds one base ref so a\n * consumer material's bind/rebind churn can never drive it to zero. `resize()` mints a FRESH wrapper (new\n * identity) so the consumer's `setShaderTexture` sees the change and rebuilds its bind group against the new\n * view; the old texture stays alive until the consumer releases its own ref (no destroy-while-referenced).\n */\n\nimport { TU, SS } from \"../engine/gpu-flags.js\";\nimport { acquireTexture, releaseTexture, getOrCreateSampler } from \"../resource/gpu-pool.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { Task } from \"./task.js\";\n\n/** Full mip chain length for a width/height (log2 of the larger side + 1). */\nfunction mipLevelCount(width: number, height: number): number {\n return Math.floor(Math.log2(Math.max(width, height))) + 1;\n}\n\nconst COPY_SHADER = `@group(0)@binding(0)var src:texture_depth_2d;\nstruct V{@builtin(position)p:vec4f};\n@vertex fn vs(@builtin(vertex_index)i:u32)->V{let p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3))[i];return V(vec4f(p,0,1));}\n@fragment fn fs(@builtin(position)fc:vec4f)->@location(0)f32{return textureLoad(src,vec2<i32>(fc.xy),0);}`;\n\n/** REDUCE fragment: `op` is `min` or `max` of the four child texels of the previous level. */\nfunction reduceShader(op: \"min\" | \"max\"): string {\n return `@group(0)@binding(0)var src:texture_2d<f32>;\nstruct V{@builtin(position)p:vec4f};\n@vertex fn vs(@builtin(vertex_index)i:u32)->V{let p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3))[i];return V(vec4f(p,0,1));}\n@fragment fn fs(@builtin(position)fc:vec4f)->@location(0)f32{\n let c=vec2<i32>(fc.xy)*2;\n let d=vec2<i32>(textureDimensions(src))-vec2<i32>(1,1);\n let x1=min(c.x+1,d.x); let y1=min(c.y+1,d.y);\n let a=textureLoad(src,vec2<i32>(c.x,c.y),0).r;\n let b=textureLoad(src,vec2<i32>(x1,c.y),0).r;\n let e=textureLoad(src,vec2<i32>(c.x,y1),0).r;\n let f=textureLoad(src,vec2<i32>(x1,y1),0).r;\n return ${op}(${op}(a,b),${op}(e,f));\n}`;\n}\n\n/** How each coarser pyramid level combines its four child texels. */\nexport type DepthPyramidReduce = \"min\" | \"max\";\n\nexport interface DepthPyramidOptions {\n /** Mip-0 width — match the source depth texture. */\n width: number;\n /** Mip-0 height — match the source depth texture. */\n height: number;\n /** Child-texel combine: `max` (default; reverse-Z nearest-surface Hi-Z) or `min` (forward-Z, or\n * reverse-Z farthest-occluder for occlusion culling). */\n reduce?: DepthPyramidReduce;\n}\n\n/** A rebuildable hierarchical depth pyramid. Create with `createDepthPyramid`; drive its per-frame build with\n * `createDepthPyramidTask` (in-frame) or by calling `build()` yourself. */\nexport interface DepthPyramid {\n /** `r32float`, full mip chain, nearest sampler. Bind to a material; read `textureLoad(tex, coord, mip)`.\n * A `resize()` replaces this wrapper (new identity) — re-read it and re-bind after a resize. */\n readonly texture: Texture2D;\n /** Number of mip levels in the current pyramid. */\n readonly mipCount: number;\n /** Re-derive the pyramid from `depthTexture` (a `texture_depth_2d` of matching mip-0 size). Pass the frame\n * `encoder` to record the COPY/REDUCE passes in-frame (e.g. after a depth prepass, before the consumer that\n * samples the pyramid); omit it to run on a private encoder + submit immediately. */\n build(depthTexture: Texture2D, encoder?: GPUCommandEncoder): void;\n /** Reallocate the pyramid texture at a new mip-0 size (call when the source depth target resizes). No-op if\n * unchanged. Mint a new `texture` wrapper on a real change; safe to call any time (does not destroy the old\n * texture while a consumer still references it). */\n resize(width: number, height: number): void;\n /** Release the pyramid's base texture ref (frees the GPU texture once no consumer holds it). */\n dispose(): void;\n}\n\ninterface EngineDevice {\n _device: GPUDevice;\n}\n\n/** Create a hierarchical depth pyramid sized `width`×`height`. Build it each frame from the live depth texture\n * (via `createDepthPyramidTask`, or `build()` directly). Owns its COPY/REDUCE pipelines + the mipped texture. */\nexport function createDepthPyramid(engine: EngineContext, opts: DepthPyramidOptions): DepthPyramid {\n const device = (engine as unknown as EngineDevice)._device;\n const reduce = opts.reduce ?? \"max\";\n const sampler = getOrCreateSampler(engine, { minFilter: \"nearest\", magFilter: \"nearest\", addressModeU: \"clamp-to-edge\", addressModeV: \"clamp-to-edge\" });\n\n const copyBGL = device.createBindGroupLayout({\n entries: [{ binding: 0, visibility: SS.FRAGMENT, texture: { sampleType: \"depth\", viewDimension: \"2d\" } }],\n });\n const reduceBGL = device.createBindGroupLayout({\n entries: [{ binding: 0, visibility: SS.FRAGMENT, texture: { sampleType: \"unfilterable-float\", viewDimension: \"2d\" } }],\n });\n const mk = (code: string, layout: GPUBindGroupLayout): GPURenderPipeline =>\n device.createRenderPipeline({\n layout: device.createPipelineLayout({ bindGroupLayouts: [layout] }),\n vertex: { module: device.createShaderModule({ code }), entryPoint: \"vs\" },\n fragment: { module: device.createShaderModule({ code }), entryPoint: \"fs\", targets: [{ format: \"r32float\" }] },\n primitive: { topology: \"triangle-list\" },\n });\n const copyPipeline = mk(COPY_SHADER, copyBGL);\n const reducePipeline = mk(reduceShader(reduce), reduceBGL);\n\n let w = Math.max(1, opts.width | 0);\n let h = Math.max(1, opts.height | 0);\n let mips = mipLevelCount(w, h);\n\n function makeTexture(): GPUTexture {\n return device.createTexture({\n label: \"depth-pyramid\",\n size: { width: w, height: h },\n format: \"r32float\",\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,\n mipLevelCount: mips,\n });\n }\n function makeWrapper(tex: GPUTexture): Texture2D {\n // One base ref so a consuming material's per-version release/acquire churn never drives the pool count to\n // 0 and destroys the texture out from under us. `_sampleType: \"float\"` — r32float sampled as unfilterable float.\n const wr = { texture: tex, view: tex.createView(), sampler, width: w, height: h, _sampleType: \"float\" } as Texture2D;\n acquireTexture(wr);\n return wr;\n }\n\n let gpuTex = makeTexture();\n let wrapper = makeWrapper(gpuTex);\n\n // Per-frame GPU objects cached across build() calls and rebuilt only on resize(): the mip-0 COPY target view and,\n // for each coarser level, a { dst view, REDUCE bind group } pair (the reduce bind group reads the previous level\n // of our own texture, so it only changes when the texture is reallocated). The COPY bind group reads the EXTERNAL\n // source depth, so it is rebuilt lazily only when that source Texture2D changes identity (e.g. a canvas-resize\n // reallocation). This keeps build() free of per-frame view/bind-group churn.\n let copyDstView: GPUTextureView;\n let reduceLevels: { dst: GPUTextureView; bindGroup: GPUBindGroup }[] = [];\n let copyBindGroup: GPUBindGroup | null = null;\n let copyBindGroupSource: Texture2D | null = null;\n\n function rebuildViews(): void {\n copyDstView = gpuTex.createView({ baseMipLevel: 0, mipLevelCount: 1 });\n reduceLevels = [];\n for (let mip = 1; mip < mips; mip++) {\n const src = gpuTex.createView({ baseMipLevel: mip - 1, mipLevelCount: 1 });\n const dst = gpuTex.createView({ baseMipLevel: mip, mipLevelCount: 1 });\n reduceLevels.push({ dst, bindGroup: device.createBindGroup({ layout: reduceBGL, entries: [{ binding: 0, resource: src }] }) });\n }\n // The texture identity changed, so the source-keyed COPY bind group is stale — force a rebuild next build().\n copyBindGroup = null;\n copyBindGroupSource = null;\n }\n rebuildViews();\n\n return {\n get texture(): Texture2D {\n return wrapper;\n },\n get mipCount(): number {\n return mips;\n },\n build(depthTexture: Texture2D, encoder?: GPUCommandEncoder): void {\n const enc = encoder ?? device.createCommandEncoder();\n // COPY bind group reads the external source depth; rebuild only when that source changes identity.\n if (copyBindGroup === null || copyBindGroupSource !== depthTexture) {\n copyBindGroup = device.createBindGroup({ layout: copyBGL, entries: [{ binding: 0, resource: depthTexture.view }] });\n copyBindGroupSource = depthTexture;\n }\n // mip 0 ← source depth.\n const copyPass = enc.beginRenderPass({\n label: \"depth-pyramid-copy\",\n colorAttachments: [{ view: copyDstView, loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } }],\n });\n copyPass.setPipeline(copyPipeline);\n copyPass.setBindGroup(0, copyBindGroup);\n copyPass.draw(3);\n copyPass.end();\n // mips 1..N ← min/max reduction of the previous level.\n for (const level of reduceLevels) {\n const pass = enc.beginRenderPass({\n label: \"depth-pyramid-reduce\",\n colorAttachments: [{ view: level.dst, loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } }],\n });\n pass.setPipeline(reducePipeline);\n pass.setBindGroup(0, level.bindGroup);\n pass.draw(3);\n pass.end();\n }\n // Submit only when we own the encoder. With an external (frame) encoder the frame graph submits it,\n // and WebGPU auto-inserts the depth→sampled barrier between the source-producing pass and our COPY.\n if (!encoder) {\n device.queue.submit([enc.finish()]);\n }\n },\n resize(nw: number, nh: number): void {\n const cw = Math.max(1, nw | 0);\n const ch = Math.max(1, nh | 0);\n if (cw === w && ch === h) {\n return;\n }\n w = cw;\n h = ch;\n mips = mipLevelCount(w, h);\n const old = wrapper;\n gpuTex = makeTexture();\n wrapper = makeWrapper(gpuTex); // fresh identity → consumer's setShaderTexture rebuilds against the new view\n rebuildViews(); // cached views/bind groups point at the old texture — rebuild them against the new one\n releaseTexture(old); // drop OUR base ref; the old texture frees once the consumer releases its ref too\n },\n dispose(): void {\n releaseTexture(wrapper);\n },\n };\n}\n\n/** Options for `createDepthPyramidTask`. */\nexport interface DepthPyramidTaskOptions {\n /** The pyramid to build each frame. The task ADOPTS it — the frame graph disposes it on graph dispose, so do\n * not also dispose it yourself. */\n pyramid: DepthPyramid;\n /** The live source depth texture for this frame (e.g. a depth-prepass target). Return `null` to skip the\n * build this frame (e.g. before the source exists, or when nothing consumes the pyramid). */\n source: () => Texture2D | null;\n}\n\n/** Create a frame-graph task that rebuilds `pyramid` from `source()` into the FRAME command encoder each frame.\n * Order it right after the pass that produces the depth (e.g. `addTaskAfter(scene, task, depthPrepassTask)`) so\n * the pyramid reflects THIS frame's depth. Resize the pyramid to the source's size before the frame is recorded\n * (the source depth target only changes size on a canvas resize). */\nexport function createDepthPyramidTask(engine: EngineContext, scene: SceneContext, opts: DepthPyramidTaskOptions): Task {\n const { pyramid, source } = opts;\n return {\n name: \"depth-pyramid\",\n engine,\n scene,\n _passes: [],\n record(): void {\n /* No recorded Pass objects — the COPY/REDUCE passes are recorded straight into the frame encoder in execute(). */\n },\n execute(): number {\n const src = source();\n if (!src) {\n return 0;\n }\n pyramid.build(src, engine._currentEncoder);\n return pyramid.mipCount;\n },\n dispose(): void {\n pyramid.dispose();\n },\n };\n}\n"],"names":[],"mappings":"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"}
|