@woosh/meep-engine 3.46.0 → 3.49.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/build/bundle-worker-terrain.js +1 -1
- package/editor/actions/concrete/TransformModifyAction.d.ts.map +1 -1
- package/editor/actions/concrete/TransformModifyAction.js +10 -2
- package/editor/ecs/component/FieldDescriptor.js +15 -0
- package/editor/ecs/component/createObjectEditor.js +41 -12
- package/editor/ecs/component/editors/ecs/Transform64Editor.d.ts.map +1 -1
- package/editor/ecs/component/editors/ecs/Transform64Editor.js +77 -70
- package/editor/particles/effect/ParticleReferenceSimulation.d.ts +1 -2
- package/editor/particles/effect/ParticleReferenceSimulation.d.ts.map +1 -1
- package/editor/particles/effect/ParticleReferenceSimulation.js +2 -4
- package/editor/tools/TransformToolV2.d.ts.map +1 -1
- package/editor/tools/TransformToolV2.js +4 -0
- package/editor/tools/v2/TransformControls.d.ts.map +1 -1
- package/editor/tools/v2/TransformControls.js +7 -0
- package/editor/view/ecs/EntityEditor.d.ts.map +1 -1
- package/editor/view/ecs/EntityEditor.js +4 -2
- package/editor/view/particles/effect/ParticleGraphEditorView.js +1 -1
- package/package.json +1 -1
- package/src/core/collection/array/array_insert_at.d.ts +16 -0
- package/src/core/collection/array/array_insert_at.d.ts.map +1 -0
- package/src/core/collection/array/array_insert_at.js +32 -0
- package/src/core/collection/array/array_remove_at.d.ts +15 -0
- package/src/core/collection/array/array_remove_at.d.ts.map +1 -0
- package/src/core/collection/array/array_remove_at.js +30 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts +37 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.js +172 -0
- package/src/core/geom/Quaternion.d.ts +1 -0
- package/src/core/geom/Quaternion.d.ts.map +1 -1
- package/src/core/geom/Quaternion.js +12 -48
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +9 -4
- package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +27 -11
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +21 -0
- package/src/engine/ecs/transform/t64_look_rotation.d.ts +4 -4
- package/src/engine/ecs/transform/t64_look_rotation.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_look_rotation.js +7 -18
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +30 -1
- package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts +2 -2
- package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts.map +1 -1
- package/src/engine/graphics/ecs/particles/ParticleEffect.js +7 -7
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts +8 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.js +11 -3
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.d.ts +26 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.d.ts.map +1 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.js +91 -0
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +6 -0
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.js +72 -29
- package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -1
- package/src/engine/graphics3/GraphicsEngine.js +8 -1
- package/src/engine/graphics3/ParticipatingMedia.d.ts +84 -1
- package/src/engine/graphics3/ParticipatingMedia.d.ts.map +1 -1
- package/src/engine/graphics3/ParticipatingMedia.js +139 -5
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts +6 -2
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.js +29 -4
- package/src/engine/graphics3/ParticipatingMediaSerializationUpgrader_0_1.d.ts +10 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationUpgrader_0_1.js +38 -0
- package/src/engine/graphics3/ParticipatingMediaSystem.d.ts.map +1 -1
- package/src/engine/graphics3/ParticipatingMediaSystem.js +46 -3
- package/src/engine/input/devices/KeyboardDevice.d.ts +1 -0
- package/src/engine/input/devices/KeyboardDevice.d.ts.map +1 -1
- package/src/engine/input/devices/KeyboardDevice.js +7 -6
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.d.ts.map +1 -1
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +15 -2
- package/src/engine/network/CONGESTION_CONTROL.md +9 -9
- package/src/engine/network/MESSAGE_TRANSPORT.md +364 -0
- package/src/engine/network/NetworkSession.d.ts +47 -16
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +556 -292
- package/src/engine/network/README.md +104 -28
- package/src/engine/network/SMOOTHNESS_DESIGN.md +13 -5
- package/src/engine/network/diagnostics/BandwidthMeter.d.ts +1 -1
- package/src/engine/network/diagnostics/BandwidthMeter.js +1 -1
- package/src/engine/network/orchestrator/HostJoin.d.ts +111 -0
- package/src/engine/network/orchestrator/HostJoin.d.ts.map +1 -0
- package/src/engine/network/orchestrator/HostJoin.js +271 -0
- package/src/engine/network/orchestrator/NetworkPeer.d.ts +151 -112
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +450 -499
- package/src/engine/network/orchestrator/PendingSlices.d.ts +30 -0
- package/src/engine/network/orchestrator/PendingSlices.d.ts.map +1 -0
- package/src/engine/network/orchestrator/PendingSlices.js +83 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts +34 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts.map +1 -0
- package/src/engine/network/orchestrator/ReliableFrames.js +96 -0
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +77 -10
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +236 -61
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +59 -23
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +213 -198
- package/src/engine/network/replication/Replicator.d.ts +15 -4
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +57 -17
- package/src/engine/network/sim/ActionLog.d.ts +32 -5
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +47 -5
- package/src/engine/network/sim/SimActionExecutor.d.ts +42 -2
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +100 -4
- package/src/engine/network/sim/Snapshotter.d.ts +12 -0
- package/src/engine/network/sim/Snapshotter.d.ts.map +1 -1
- package/src/engine/network/sim/Snapshotter.js +43 -0
- package/src/engine/network/state/Baseline.d.ts +1 -1
- package/src/engine/network/state/Baseline.js +1 -1
- package/src/engine/network/state/FrameBufferRing.d.ts +25 -6
- package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -1
- package/src/engine/network/state/FrameBufferRing.js +51 -6
- package/src/engine/network/state/InputRing.d.ts +4 -0
- package/src/engine/network/state/InputRing.d.ts.map +1 -1
- package/src/engine/network/state/InputRing.js +7 -0
- package/src/engine/network/state/RecordArrivalRing.d.ts +57 -0
- package/src/engine/network/state/RecordArrivalRing.d.ts.map +1 -0
- package/src/engine/network/state/RecordArrivalRing.js +144 -0
- package/src/engine/network/transport/DeferredTransport.d.ts.map +1 -1
- package/src/engine/network/transport/DeferredTransport.js +1 -0
- package/src/engine/network/transport/LoopbackTransport.d.ts.map +1 -1
- package/src/engine/network/transport/LoopbackTransport.js +4 -2
- package/src/engine/network/transport/Transport.d.ts +7 -0
- package/src/engine/network/transport/Transport.d.ts.map +1 -1
- package/src/engine/network/transport/Transport.js +8 -0
- package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/NodeUDPTransport.js +20 -5
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +8 -0
- package/src/engine/network/transport/adapters/WebTransportTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebTransportTransport.js +6 -0
- package/src/engine/network/transport/connection/Connection.d.ts +191 -0
- package/src/engine/network/transport/connection/Connection.d.ts.map +1 -0
- package/src/engine/network/transport/connection/Connection.js +1262 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts +94 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RangeSet.js +260 -0
- package/src/engine/network/transport/connection/RxStream.d.ts +48 -0
- package/src/engine/network/transport/connection/RxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RxStream.js +211 -0
- package/src/engine/network/transport/connection/TxStream.d.ts +90 -0
- package/src/engine/network/transport/connection/TxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/TxStream.js +243 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts +17 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts.map +1 -0
- package/src/engine/network/transport/connection/bytes_copy.js +34 -0
- package/src/engine/network/transport/connection/varint.d.ts +46 -0
- package/src/engine/network/transport/connection/varint.d.ts.map +1 -0
- package/src/engine/network/transport/connection/varint.js +107 -0
- package/src/engine/physics/cloth/MEASUREMENTS.md +354 -0
- package/src/engine/physics/cloth/PLAN.md +85 -5
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +0 -12
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +0 -13
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +2 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +7 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +4 -15
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +2 -1
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +6 -1
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_build_rows.js +20 -10
- package/src/engine/physics/cloth/playground/collide.html +5 -3
- package/src/engine/physics/cloth/playground/collide_main.js +14 -13
- package/src/engine/physics/cloth/solver/ClothState.d.ts +30 -2
- package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/ClothState.js +62 -4
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +11 -3
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_self_find.js +52 -11
- package/src/engine/physics/cloth/solver/cloth_self_radius.d.ts +42 -0
- package/src/engine/physics/cloth/solver/cloth_self_radius.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_self_radius.js +64 -0
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +99 -24
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +102 -25
- package/src/engine/physics/cloth/solver/cloth_step.d.ts +5 -1
- package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step.js +13 -3
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +0 -1
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step_instance.js +12 -14
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts +23 -4
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +36 -8
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +4 -2
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts +38 -7
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitter.js +35 -7
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.js +48 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts +12 -2
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.js +173 -9
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts +9 -3
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/LiveEmitterSet.js +28 -8
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts +8 -0
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.js +51 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.js +15 -1
- package/src/engine/sound/sopra/README.md +768 -644
- package/src/engine/sound/sopra/SopraEngine.d.ts +104 -8
- package/src/engine/sound/sopra/SopraEngine.d.ts.map +1 -1
- package/src/engine/sound/sopra/SopraEngine.js +327 -12
- package/src/engine/sound/sopra/definition/EventDescription.d.ts +28 -2
- package/src/engine/sound/sopra/definition/EventDescription.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescription.js +55 -5
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts +10 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +77 -55
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts +31 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.js +75 -0
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts +38 -9
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +34 -5
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts +7 -2
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +137 -122
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts +3 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.js +146 -131
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts +1 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +6 -1
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts +44 -2
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/BusGraph.js +83 -43
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts +96 -0
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectChain.js +286 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts +123 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.js +320 -0
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts +55 -5
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/EventInstance.js +201 -26
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts +2 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +6 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts +15 -0
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +32 -0
- package/src/engine/sound/sopra/util/MockAudioContext.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/MockAudioContext.js +3 -0
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts +13 -3
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/fadeOutAndStop.js +25 -13
- package/src/shade/RENDERER_CONTRACT.md +6 -3
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts +24 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts.map +1 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.js +34 -0
- package/src/shade/device/ShadeDeviceFailure.d.ts +12 -5
- package/src/shade/device/ShadeDeviceFailure.d.ts.map +1 -1
- package/src/shade/device/ShadeDeviceFailure.js +17 -8
- package/src/shade/device/ShadeDeviceFailureReason.d.ts +1 -1
- package/src/shade/device/ShadeDeviceFailureReason.js +2 -2
- package/src/shade/device/mock/SoftwareGPUDevice.d.ts +15 -0
- package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUDevice.js +21 -0
- package/src/shade/device/pipeline/ComputePipelineManager.d.ts +20 -0
- package/src/shade/device/pipeline/ComputePipelineManager.d.ts.map +1 -1
- package/src/shade/device/pipeline/ComputePipelineManager.js +80 -6
- package/src/shade/device/pipeline/PipelineEnquiry.d.ts +52 -0
- package/src/shade/device/pipeline/PipelineEnquiry.d.ts.map +1 -0
- package/src/shade/device/pipeline/PipelineEnquiry.js +63 -0
- package/src/shade/device/pipeline/RenderPipelineManager.d.ts +21 -0
- package/src/shade/device/pipeline/RenderPipelineManager.d.ts.map +1 -1
- package/src/shade/device/pipeline/RenderPipelineManager.js +84 -4
- package/src/shade/device/shade_device_floor_unmet.d.ts +13 -0
- package/src/shade/device/shade_device_floor_unmet.d.ts.map +1 -0
- package/src/shade/device/shade_device_floor_unmet.js +32 -0
- package/src/shade/playground/contact_shadows/ContactShadowLab.d.ts +137 -0
- package/src/shade/playground/contact_shadows/ContactShadowLab.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/ContactShadowLab.js +654 -0
- package/src/shade/playground/contact_shadows/README.md +126 -0
- package/src/shade/playground/contact_shadows/index.html +191 -0
- package/src/shade/playground/contact_shadows/main.d.ts +2 -0
- package/src/shade/playground/contact_shadows/main.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/main.js +888 -0
- package/src/shade/playground/contact_shadows/scenes.d.ts +48 -0
- package/src/shade/playground/contact_shadows/scenes.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/scenes.js +620 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_composite.d.ts +36 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_composite.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_composite.js +245 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_reference.d.ts +15 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_reference.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_reference.js +120 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_stats.d.ts +55 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_stats.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_stats.js +216 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_view.d.ts +20 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_view.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_view.js +114 -0
- package/src/shade/playground/contact_shadows/shader_contact_shadow_march.d.ts +11 -0
- package/src/shade/playground/contact_shadows/shader_contact_shadow_march.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_shadow_march.js +90 -0
- package/src/shade/playground/contact_shadows/textures.d.ts +16 -0
- package/src/shade/playground/contact_shadows/textures.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/textures.js +123 -0
- package/src/shade/playground/particle_ecs/README.md +1 -1
- package/src/shade/playground/particle_ecs/effects/flame.json +1932 -1881
- package/src/shade/playground/particle_ecs/effects/smoke.json +99 -1
- package/src/shade/playground/particle_ecs/effects/soot.json +152 -145
- package/src/shade/playground/tonemap_sdr/README.md +90 -0
- package/src/shade/playground/tonemap_sdr/ToneMapCompare.d.ts +105 -0
- package/src/shade/playground/tonemap_sdr/ToneMapCompare.d.ts.map +1 -0
- package/src/shade/playground/tonemap_sdr/ToneMapCompare.js +380 -0
- package/src/shade/playground/tonemap_sdr/chunk_tonemap_gt7_sdr_reference.d.ts +32 -0
- package/src/shade/playground/tonemap_sdr/chunk_tonemap_gt7_sdr_reference.d.ts.map +1 -0
- package/src/shade/playground/tonemap_sdr/chunk_tonemap_gt7_sdr_reference.js +104 -0
- package/src/shade/playground/tonemap_sdr/index.html +90 -0
- package/src/shade/playground/tonemap_sdr/main.d.ts +2 -0
- package/src/shade/playground/tonemap_sdr/main.d.ts.map +1 -0
- package/src/shade/playground/tonemap_sdr/main.js +306 -0
- package/src/shade/playground/tonemap_sdr/scenes.d.ts +26 -0
- package/src/shade/playground/tonemap_sdr/scenes.d.ts.map +1 -0
- package/src/shade/playground/tonemap_sdr/scenes.js +404 -0
- package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
- package/src/shade/playground/volumetrics_froxel/main.js +85 -4
- package/src/shade/playground/water_refraction/README.md +26 -18
- package/src/shade/playground/water_refraction/index.html +1 -1
- package/src/shade/renderer/Renderer.d.ts +37 -3
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +237 -67
- package/src/shade/renderer/ShadeToneMappingMode.d.ts +14 -0
- package/src/shade/renderer/ShadeToneMappingMode.d.ts.map +1 -0
- package/src/shade/renderer/ShadeToneMappingMode.js +30 -0
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +9 -0
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +14 -0
- package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +5 -3
- package/src/shade/renderer/buffer/GPUBufferAllocator.d.ts.map +1 -1
- package/src/shade/renderer/buffer/GPUBufferAllocator.js +9 -0
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts +21 -12
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts.map +1 -1
- package/src/shade/renderer/buffer/buffer_pool_ops.js +18 -19
- package/src/shade/renderer/buffer/table/GPUDatabase.d.ts +7 -0
- package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/GPUDatabase.js +12 -0
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts +8 -0
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +12 -0
- package/src/shade/renderer/camera/GPUCameraContext.d.ts.map +1 -1
- package/src/shade/renderer/camera/GPUCameraContext.js +19 -8
- package/src/shade/renderer/deferred/chunk_read_gBuffer_material.d.ts.map +1 -1
- package/src/shade/renderer/deferred/chunk_read_gBuffer_material.js +4 -0
- package/src/shade/renderer/deferred/chunk_shade_standard_material_direct.d.ts.map +1 -1
- package/src/shade/renderer/deferred/chunk_shade_standard_material_direct.js +4 -0
- package/src/shade/renderer/deferred/chunk_shade_standard_material_direct_restir.d.ts.map +1 -1
- package/src/shade/renderer/deferred/chunk_shade_standard_material_direct_restir.js +4 -0
- package/src/shade/renderer/deferred/shader_deferred_main.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_deferred_main.js +3 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts +6 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_tonemap_HDR.js +13 -3
- package/src/shade/renderer/deferred/shader_tonemap_HDR_none.d.ts +9 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_none.d.ts.map +1 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_none.js +63 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.d.ts +10 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.d.ts.map +1 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.js +87 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR.d.ts +6 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_tonemap_LDR.js +23 -5
- package/src/shade/renderer/deferred/shader_tonemap_LDR_none.d.ts +9 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_none.d.ts.map +1 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_none.js +68 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.d.ts +10 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.d.ts.map +1 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.js +73 -0
- package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/MeshletBatch.js +58 -9
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +35 -25
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +97 -196
- package/src/shade/renderer/geometry/sdf/shader_build_sdf.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/shader_build_sdf.js +121 -129
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.js +3 -0
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +4 -0
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_indirect_lighting.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_indirect_lighting.js +4 -0
- package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.js +3 -0
- package/src/shade/renderer/global_illumination/lpv/deprecated/probe_trace_compute_shader_code.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/lpv/deprecated/probe_trace_compute_shader_code.js +4 -0
- package/src/shade/renderer/global_illumination/probe/octahedral/graph_sample_light_probes.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/graph_sample_light_probes.js +4 -0
- package/src/shade/renderer/global_illumination/shader_resolve_indirect_lighting.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/shader_resolve_indirect_lighting.js +4 -0
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +131 -1
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.d.ts +7 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.js +45 -38
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.d.ts +2 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.js +81 -79
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.d.ts +2 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.js +5 -3
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_internal_children.d.ts +21 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_internal_children.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_internal_children.js +42 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_morton_code.d.ts +19 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_morton_code.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_morton_code.js +44 -0
- package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts +23 -5
- package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +139 -23
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_build_single_workgroup.d.ts +25 -0
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_build_single_workgroup.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_build_single_workgroup.js +179 -0
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts +2 -2
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +7 -16
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts +3 -4
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +6 -23
- package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts +11 -0
- package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.js +14 -3
- package/src/shade/renderer/gpu_primitive/indirect/build_indirect_draw_command.d.ts +10 -0
- package/src/shade/renderer/gpu_primitive/indirect/build_indirect_draw_command.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/indirect/build_indirect_draw_command.js +13 -3
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +10 -0
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +14 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_comparator.d.ts +26 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_comparator.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_comparator.js +52 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_workgroup.d.ts +32 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_workgroup.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_workgroup.js +89 -0
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +10 -0
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +20 -1
- package/src/shade/renderer/gpu_primitive/test/gpu_test.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/test/gpu_test.js +8 -11
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +10 -0
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +294 -281
- package/src/shade/renderer/light/GPULightCollection.d.ts +8 -0
- package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/GPULightCollection.js +18 -1
- package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts +8 -0
- package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/cull/graph_cull_lights.js +234 -218
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts +7 -0
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +13 -0
- package/src/shade/renderer/light/cluster/graph_build_light_clusters.d.ts +7 -0
- package/src/shade/renderer/light/cluster/graph_build_light_clusters.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/graph_build_light_clusters.js +16 -2
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts +10 -0
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/execute_filter_environment_map.js +13 -0
- package/src/shade/renderer/lightmap/GPULightMap.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/GPULightMap.js +3 -0
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.js +4 -0
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.js +4 -0
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.d.ts +16 -4
- package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.js +38 -8
- package/src/shade/renderer/particles/DESIGN.md +49 -7
- package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +453 -0
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts +5 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +13 -5
- package/src/shade/renderer/particles/data/particle_emitter_record.js +2 -2
- package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +12 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts +60 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +156 -0
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +2 -2
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/ParticleEmitter.js +8 -8
- package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.js +6 -4
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts +7 -6
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +91 -58
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +10 -0
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +5 -1
- package/src/shade/renderer/path_tracer/graph_path_trace_scene.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/graph_path_trace_scene.js +6 -0
- package/src/shade/renderer/pool/TransientResourcePool.d.ts +24 -0
- package/src/shade/renderer/pool/TransientResourcePool.d.ts.map +1 -1
- package/src/shade/renderer/pool/TransientResourcePool.js +41 -10
- package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.d.ts +7 -0
- package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +18 -0
- package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.js +1 -0
- package/src/shade/renderer/postprocess/denoise/shader_temporal_reprojection_luma.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/denoise/shader_temporal_reprojection_luma.js +6 -4
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts +11 -0
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +16 -0
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts +10 -0
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/GTAO.js +16 -0
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +32 -10
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +3 -0
- package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.js +6 -3
- package/src/shade/renderer/postprocess/taa/TAA.d.ts +12 -0
- package/src/shade/renderer/postprocess/taa/TAA.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/taa/TAA.js +15 -0
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts +7 -0
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +13 -0
- package/src/shade/renderer/rasterize/TemplatePassDescriptor.d.ts +31 -3
- package/src/shade/renderer/rasterize/TemplatePassDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/TemplatePassDescriptor.js +79 -4
- package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.d.ts +17 -0
- package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.js +35 -4
- package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts +7 -0
- package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.js +182 -169
- package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.js +20 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_extract_meshlets_from_bucket.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_extract_meshlets_from_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_extract_meshlets_from_bucket.js +18 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.js +20 -1
- package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts +7 -0
- package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.js +187 -170
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.js +19 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts +13 -0
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.js +25 -1
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +20 -0
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.js +6 -0
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.js +6 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +3 -2
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +3 -2
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +7 -2
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +12 -4
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.js +4 -3
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.js +4 -3
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts +2 -1
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +11 -3
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.js +4 -3
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +4 -3
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts +15 -0
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +35 -2
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts +14 -0
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +32 -4
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts +17 -0
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +34 -4
- package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts +5 -3
- package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/chunk_restir_resolve.js +8 -3
- package/src/shade/renderer/restir/di/graph_restir_di.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/graph_restir_di.js +1 -0
- package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +5 -1
- package/src/shade/renderer/restir/reservoir/shader.d.ts.map +1 -1
- package/src/shade/renderer/restir/reservoir/shader.js +7 -4
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts +7 -0
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +13 -1
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +10 -0
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +19 -0
- package/src/shade/renderer/scene/SceneManager.d.ts +9 -0
- package/src/shade/renderer/scene/SceneManager.d.ts.map +1 -1
- package/src/shade/renderer/scene/SceneManager.js +11 -0
- package/src/shade/renderer/scene/hierarchy/graph_nodes_update_transform_hierarchy.d.ts +11 -0
- package/src/shade/renderer/scene/hierarchy/graph_nodes_update_transform_hierarchy.d.ts.map +1 -1
- package/src/shade/renderer/scene/hierarchy/graph_nodes_update_transform_hierarchy.js +17 -0
- package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.d.ts +11 -0
- package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.d.ts.map +1 -1
- package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.js +18 -1
- package/src/shade/renderer/shader/ComputeShader.d.ts +12 -0
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +71 -2
- package/src/shade/renderer/shader/ImageShader.d.ts +27 -8
- package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ImageShader.js +299 -218
- package/src/shade/renderer/shader/ShaderDescriptor.d.ts +21 -0
- package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/ShaderDescriptor.js +71 -1
- package/src/shade/renderer/shader/chunk/camera/chunk_project_view_position_from_depth.d.ts +17 -0
- package/src/shade/renderer/shader/chunk/camera/chunk_project_view_position_from_depth.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/camera/chunk_project_view_position_from_depth.js +45 -0
- package/src/shade/renderer/shader/chunk/camera/chunk_screen_coordinate_to_view.js +3 -3
- package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.d.ts +1 -1
- package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.js +62 -62
- package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +318 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +237 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.d.ts +17 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js +22 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.d.ts +14 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.js +28 -15
- package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.d.ts +12 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.js +128 -110
- package/src/shade/renderer/shader/chunk/geometry/ray/chunk_offset_ray_from_depth.d.ts +20 -0
- package/src/shade/renderer/shader/chunk/geometry/ray/chunk_offset_ray_from_depth.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/ray/chunk_offset_ray_from_depth.js +33 -0
- package/src/shade/renderer/shader/chunk/light/chunk_compute_multiscattering_specular.d.ts +4 -0
- package/src/shade/renderer/shader/chunk/light/chunk_compute_multiscattering_specular.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/light/chunk_compute_multiscattering_specular.js +12 -1
- package/src/shade/renderer/shader/chunk/material/MATERIAL_SHADING_INFO_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/material/MATERIAL_SHADING_INFO_STRUCT.js +7 -0
- package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +108 -0
- package/src/shade/renderer/shader/chunk/material/chunk_compute_indirect_specular.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/material/chunk_compute_indirect_specular.js +23 -4
- package/src/shade/renderer/shader/chunk/material/chunk_re_direct_multiscatter.d.ts +18 -0
- package/src/shade/renderer/shader/chunk/material/chunk_re_direct_multiscatter.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/material/chunk_re_direct_multiscatter.js +56 -0
- package/src/shade/renderer/shader/chunk/material/chunk_re_indirect_specular_physical.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/material/chunk_re_indirect_specular_physical.js +2 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_linear_ray.d.ts +43 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_linear_ray.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_linear_ray.js +319 -0
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts +33 -0
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts.map +1 -1
- package/src/shade/renderer/shader/compiler/CodeChunk.js +140 -0
- package/src/shade/renderer/shader/compiler/CodeChunkChoice.d.ts +74 -0
- package/src/shade/renderer/shader/compiler/CodeChunkChoice.d.ts.map +1 -0
- package/src/shade/renderer/shader/compiler/CodeChunkChoice.js +166 -0
- package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +680 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitch.d.ts +86 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitch.d.ts.map +1 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitch.js +178 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitchSet.d.ts +67 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitchSet.d.ts.map +1 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitchSet.js +205 -0
- package/src/shade/renderer/shadow/contact/CONTACT_SHADOW_WAVE_SIZE.d.ts +14 -0
- package/src/shade/renderer/shadow/contact/CONTACT_SHADOW_WAVE_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/CONTACT_SHADOW_WAVE_SIZE.js +13 -0
- package/src/shade/renderer/shadow/contact/ContactShadowDispatchList.d.ts +65 -0
- package/src/shade/renderer/shadow/contact/ContactShadowDispatchList.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/ContactShadowDispatchList.js +252 -0
- package/src/shade/renderer/shadow/contact/FINDINGS.md +413 -0
- package/src/shade/renderer/shadow/contact/chunk_contact_shadow_wavefront_extents.d.ts +29 -0
- package/src/shade/renderer/shadow/contact/chunk_contact_shadow_wavefront_extents.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/chunk_contact_shadow_wavefront_extents.js +105 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.d.ts +29 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.js +39 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_wavefront.d.ts +29 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_wavefront.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_wavefront.js +92 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.d.ts +29 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.js +128 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_wavefront.d.ts +52 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_wavefront.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_wavefront.js +358 -0
- package/src/shade/renderer/shadow/map/ShadowDirectionalTechnique.d.ts +10 -0
- package/src/shade/renderer/shadow/map/ShadowDirectionalTechnique.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/ShadowDirectionalTechnique.js +12 -0
- package/src/shade/renderer/shadow/map/shader/SHADOW_DIRECTIONAL_TECHNIQUE.d.ts +13 -0
- package/src/shade/renderer/shadow/map/shader/SHADOW_DIRECTIONAL_TECHNIQUE.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/shader/SHADOW_DIRECTIONAL_TECHNIQUE.js +14 -0
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts +14 -8
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.js +20 -86
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional_cascades.d.ts +14 -0
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional_cascades.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional_cascades.js +79 -0
- package/src/shade/renderer/shadow/ray/shader_ray_shadow_code.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/shader_ray_shadow_code.js +12 -12
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +153 -151
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_directional_virtual.d.ts +13 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_directional_virtual.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_directional_virtual.js +48 -0
- package/src/shade/renderer/texture/GPUTextureContext.d.ts +10 -0
- package/src/shade/renderer/texture/GPUTextureContext.d.ts.map +1 -1
- package/src/shade/renderer/texture/GPUTextureContext.js +24 -0
- package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts +219 -0
- package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts.map +1 -0
- package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.js +671 -0
- package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.d.ts +26 -2
- package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.js +108 -4
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +5 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +6 -0
- package/src/shade/renderer/volumetrics/NOTES.md +50 -0
- package/src/shade/renderer/volumetrics/PARTICIPATING_MEDIA_VOLUME_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/PARTICIPATING_MEDIA_VOLUME_STRUCT.js +30 -1
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +51 -13
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +98 -13
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts +9 -0
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/SceneVolumetrics.js +78 -68
- package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +326 -0
- package/src/shade/renderer/volumetrics/chunk_participating_media_volume_sample.d.ts +7 -4
- package/src/shade/renderer/volumetrics/chunk_participating_media_volume_sample.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/chunk_participating_media_volume_sample.js +21 -9
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_uvw_from_clip.d.ts +19 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_uvw_from_clip.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_uvw_from_clip.js +53 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts +12 -3
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.js +85 -48
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts +4 -1
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.js +4 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +4 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +21 -1
- package/src/shade/renderer/volumetrics/noise/PARTICIPATING_MEDIA_NOISE.d.ts +98 -0
- package/src/shade/renderer/volumetrics/noise/PARTICIPATING_MEDIA_NOISE.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/PARTICIPATING_MEDIA_NOISE.js +115 -0
- package/src/shade/renderer/volumetrics/noise/VOLUMETRICS_NOISE_TILE_BAKE_SETTINGS_STRUCT.d.ts +9 -0
- package/src/shade/renderer/volumetrics/noise/VOLUMETRICS_NOISE_TILE_BAKE_SETTINGS_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/VOLUMETRICS_NOISE_TILE_BAKE_SETTINGS_STRUCT.js +24 -0
- package/src/shade/renderer/volumetrics/noise/bake_volumetrics_noise_tile.d.ts +27 -0
- package/src/shade/renderer/volumetrics/noise/bake_volumetrics_noise_tile.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/bake_volumetrics_noise_tile.js +91 -0
- package/src/shade/renderer/volumetrics/noise/chunk_participating_media_noise.d.ts +35 -0
- package/src/shade/renderer/volumetrics/noise/chunk_participating_media_noise.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/chunk_participating_media_noise.js +92 -0
- package/src/shade/renderer/volumetrics/noise/shader_volumetrics_noise_tile_bake.d.ts +10 -0
- package/src/shade/renderer/volumetrics/noise/shader_volumetrics_noise_tile_bake.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/shader_volumetrics_noise_tile_bake.js +121 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.js +38 -3
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.js +311 -290
- package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.js +28 -49
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts +3 -1
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +24 -18
- package/src/shade/renderer/water/chunk_water_transport.d.ts +0 -1
- package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
- package/src/shade/renderer/water/chunk_water_transport.js +0 -17
- package/src/shade/renderer/water/shader_water.d.ts +4 -2
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +27 -16
- package/src/shade/renderer/water/shader_water_avboit.d.ts +0 -4
- package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water_avboit.js +0 -63
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +43 -9
- package/src/view/graphics/GraphicsContextFailureView.d.ts +1 -2
- package/src/view/graphics/GraphicsContextFailureView.d.ts.map +1 -1
- package/src/view/graphics/GraphicsContextFailureView.js +1 -2
- package/src/engine/network/transport/Channel.d.ts +0 -85
- package/src/engine/network/transport/Channel.d.ts.map +0 -1
- package/src/engine/network/transport/Channel.js +0 -336
- package/src/engine/network/transport/ReliableCommandPipeline.d.ts +0 -155
- package/src/engine/network/transport/ReliableCommandPipeline.d.ts.map +0 -1
- package/src/engine/network/transport/ReliableCommandPipeline.js +0 -335
- package/src/engine/network/transport/fragments/FragmentAssembler.d.ts +0 -105
- package/src/engine/network/transport/fragments/FragmentAssembler.d.ts.map +0 -1
- package/src/engine/network/transport/fragments/FragmentAssembler.js +0 -350
- package/src/engine/network/transport/fragments/FragmentRetention.d.ts +0 -103
- package/src/engine/network/transport/fragments/FragmentRetention.d.ts.map +0 -1
- package/src/engine/network/transport/fragments/FragmentRetention.js +0 -191
- package/src/engine/network/transport/fragments/fragment_send.d.ts +0 -61
- package/src/engine/network/transport/fragments/fragment_send.d.ts.map +0 -1
- package/src/engine/network/transport/fragments/fragment_send.js +0 -157
- package/src/engine/network/transport/fragments/packet_size.d.ts +0 -99
- package/src/engine/network/transport/fragments/packet_size.d.ts.map +0 -1
- package/src/engine/network/transport/fragments/packet_size.js +0 -107
- package/src/shade/renderer/shader/chunk/color/sRGB/chunk_RRTAndODTFit.d.ts +0 -6
- package/src/shade/renderer/shader/chunk/color/sRGB/chunk_RRTAndODTFit.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/sRGB/chunk_RRTAndODTFit.js +0 -16
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_aces.d.ts +0 -7
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_aces.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_aces.js +0 -46
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_agx.d.ts +0 -10
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_agx.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_agx.js +0 -127
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_pbr_neutral.d.ts +0 -7
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_pbr_neutral.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_pbr_neutral.js +0 -39
|
@@ -0,0 +1,1262 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import Signal from "../../../../core/events/signal/Signal.js";
|
|
3
|
+
import { bytes_copy } from "./bytes_copy.js";
|
|
4
|
+
import { RangeSet } from "./RangeSet.js";
|
|
5
|
+
import { RX_ERROR, RX_NONE, RxStream } from "./RxStream.js";
|
|
6
|
+
import { TxStream } from "./TxStream.js";
|
|
7
|
+
import { varint_read, varint_size, varint_write } from "./varint.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Reliable lanes. Each is an ordered stream of messages; the lanes are independent of each other.
|
|
11
|
+
* @readonly
|
|
12
|
+
* @enum {number}
|
|
13
|
+
*/
|
|
14
|
+
export const Lane = Object.freeze({
|
|
15
|
+
/** Engine control messages, one datagram each: resume answers, DISCONNECT. Not paced. */
|
|
16
|
+
CONTROL: 0,
|
|
17
|
+
/**
|
|
18
|
+
* Action-stream frames too large for a datagram. Not paced: the stream to the peer waits on
|
|
19
|
+
* them, and it cannot wait longer than its action log's ring.
|
|
20
|
+
*/
|
|
21
|
+
FRAMES: 1,
|
|
22
|
+
/** Application messages that must arrive. Paced. */
|
|
23
|
+
USER: 2,
|
|
24
|
+
/** Large transfers: snapshot pages, state bursts. Paced, last. */
|
|
25
|
+
BULK: 3,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const LANE_COUNT = 4;
|
|
29
|
+
|
|
30
|
+
/** Lanes the token bucket holds back. */
|
|
31
|
+
const LANE_PACED = [false, false, true, true];
|
|
32
|
+
|
|
33
|
+
/** Protocol version, in the high nibble of every datagram's flags byte. */
|
|
34
|
+
const PROTOCOL_VERSION = 1;
|
|
35
|
+
|
|
36
|
+
/*
|
|
37
|
+
Wire format, one datagram:
|
|
38
|
+
|
|
39
|
+
u8 flags bit0 ACK present, bit1 packet number is 4 bytes (else 2),
|
|
40
|
+
bits 4-7 protocol version
|
|
41
|
+
u16|u32 packet number truncated, big-endian
|
|
42
|
+
[ACK] varint largest acknowledged (full packet number)
|
|
43
|
+
varint ack delay, units of 8 µs
|
|
44
|
+
varint additional range count
|
|
45
|
+
varint first range (packets below largest acknowledged, contiguous)
|
|
46
|
+
count × (varint gap, varint range length) RFC 9000 §19.3
|
|
47
|
+
frames to the end of the datagram:
|
|
48
|
+
0x01 MESSAGE varint length, bytes unreliable, one datagram at most
|
|
49
|
+
0x02 PING nothing asks for an ACK
|
|
50
|
+
0x10|lane STREAM varint offset, varint length, bytes reliable
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
const FLAG_ACK = 0x01;
|
|
54
|
+
const FLAG_PN32 = 0x02;
|
|
55
|
+
const FLAGS_KNOWN = FLAG_ACK | FLAG_PN32 | (PROTOCOL_VERSION << 4);
|
|
56
|
+
|
|
57
|
+
const FRAME_MESSAGE = 0x01;
|
|
58
|
+
const FRAME_PING = 0x02;
|
|
59
|
+
const FRAME_STREAM = 0x10;
|
|
60
|
+
const FRAME_STREAM_LANE_MASK = 0x03;
|
|
61
|
+
|
|
62
|
+
/** flags byte + 4-byte packet number */
|
|
63
|
+
const PACKET_HEADER_MAX = 5;
|
|
64
|
+
/** type byte + 2-byte varint length (datagrams stay under 16,384 bytes) */
|
|
65
|
+
const MESSAGE_FRAME_HEADER_MAX = 3;
|
|
66
|
+
/** type byte + 8-byte offset + 2-byte length */
|
|
67
|
+
const STREAM_FRAME_HEADER_MAX = 11;
|
|
68
|
+
/** a stream frame is not started with less room than this for its bytes */
|
|
69
|
+
const STREAM_FRAME_MIN_PAYLOAD = 16;
|
|
70
|
+
|
|
71
|
+
/** RFC 9002 kPacketThreshold */
|
|
72
|
+
const PACKET_THRESHOLD = 3;
|
|
73
|
+
/** RFC 9002 kInitialRtt, ms */
|
|
74
|
+
const INITIAL_RTT_MS = 333;
|
|
75
|
+
|
|
76
|
+
/** Record kinds: what a packet carried that needs news of its fate. */
|
|
77
|
+
const RECORD_MESSAGE = 1;
|
|
78
|
+
const RECORD_STREAM = 2;
|
|
79
|
+
|
|
80
|
+
/** In-flight packets at most; past this the oldest is given up as lost. */
|
|
81
|
+
const MAX_IN_FLIGHT = 1 << 16;
|
|
82
|
+
|
|
83
|
+
/** Ack delay is sent in units of 8 µs. */
|
|
84
|
+
const ACK_DELAY_UNITS_PER_MS = 125;
|
|
85
|
+
|
|
86
|
+
/** Most ranges one ACK frame may carry: a receiver refuses more. */
|
|
87
|
+
const MAX_ACK_RANGES = 64;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* One connection to one peer over a datagram {@link Transport}: numbered packets acknowledged by
|
|
91
|
+
* ranges, unreliable messages of up to a datagram with a delivery notice each, and reliable lanes
|
|
92
|
+
* that carry messages of any size up to `max_message_bytes`, paced by a token bucket.
|
|
93
|
+
*
|
|
94
|
+
* Everything queued goes out on {@link flush}, packed into as few datagrams as fit. Everything
|
|
95
|
+
* received is handled inside the transport's receive callback. Time is whatever `clock` says; the
|
|
96
|
+
* connection never reads a clock of its own.
|
|
97
|
+
*
|
|
98
|
+
* The design is in `network/MESSAGE_TRANSPORT.md`. Loss detection, RTT and the probe timeout follow
|
|
99
|
+
* QUIC (RFC 9002), packet numbers and ACK ranges RFC 9000.
|
|
100
|
+
*
|
|
101
|
+
* @author Alex Goldring
|
|
102
|
+
* @copyright Company Named Limited (c) 2026
|
|
103
|
+
*/
|
|
104
|
+
export class Connection {
|
|
105
|
+
// ---------------------------------------------------------------- configuration
|
|
106
|
+
|
|
107
|
+
/** @type {{ send(bytes: Uint8Array, length: number): void, onReceive: Signal }} */
|
|
108
|
+
#transport;
|
|
109
|
+
/** @type {function(): number} */
|
|
110
|
+
#clock;
|
|
111
|
+
#max_datagram;
|
|
112
|
+
#rate_bytes_per_ms;
|
|
113
|
+
#burst_bytes;
|
|
114
|
+
#max_ack_ranges;
|
|
115
|
+
#max_ack_delay_ms;
|
|
116
|
+
/** RFC 9002 kGranularity: the clock's resolution, one tick */
|
|
117
|
+
#granularity_ms;
|
|
118
|
+
/** acknowledgements say what was delivered; nothing is lost and nothing is probed */
|
|
119
|
+
#lossless;
|
|
120
|
+
#max_queued_bytes;
|
|
121
|
+
|
|
122
|
+
// ---------------------------------------------------------------- send side
|
|
123
|
+
|
|
124
|
+
#next_pn = 0;
|
|
125
|
+
/** largest of our packet numbers the peer has acknowledged */
|
|
126
|
+
#largest_acked = -1;
|
|
127
|
+
/** every packet below this is retired (acked or lost) */
|
|
128
|
+
#oldest_unretired = 0;
|
|
129
|
+
|
|
130
|
+
// in-flight table, indexed by packet number & (capacity - 1)
|
|
131
|
+
#pkt_capacity = 256;
|
|
132
|
+
#pkt_pn = new Float64Array(256).fill(-1);
|
|
133
|
+
#pkt_sent_time = new Float64Array(256);
|
|
134
|
+
#pkt_size = new Uint16Array(256);
|
|
135
|
+
#pkt_rec_start = new Float64Array(256);
|
|
136
|
+
#pkt_rec_count = new Uint16Array(256);
|
|
137
|
+
/** largest packet number this packet's ACK reported, -1 when it carried none */
|
|
138
|
+
#pkt_ack_largest = new Float64Array(256);
|
|
139
|
+
#in_flight_count = 0;
|
|
140
|
+
|
|
141
|
+
// records ring, indexed by absolute record index % capacity
|
|
142
|
+
#rec_capacity = 1024;
|
|
143
|
+
#rec_kind = new Uint8Array(1024);
|
|
144
|
+
#rec_id = new Int32Array(1024);
|
|
145
|
+
#rec_offset = new Float64Array(1024);
|
|
146
|
+
#rec_length = new Int32Array(1024);
|
|
147
|
+
#rec_head = 0;
|
|
148
|
+
|
|
149
|
+
// RTT, RFC 9002 §5
|
|
150
|
+
#has_rtt = false;
|
|
151
|
+
#latest_rtt = 0;
|
|
152
|
+
#smoothed_rtt = INITIAL_RTT_MS;
|
|
153
|
+
#rttvar = INITIAL_RTT_MS / 2;
|
|
154
|
+
#min_rtt = 0;
|
|
155
|
+
|
|
156
|
+
#pto_count = 0;
|
|
157
|
+
#last_ack_eliciting_sent = 0;
|
|
158
|
+
#probe_pending = false;
|
|
159
|
+
/** a probe may send one paced datagram past an empty bucket */
|
|
160
|
+
#probe_credit = false;
|
|
161
|
+
/** bytes of paced lanes sent this flush: they always get one datagram's worth */
|
|
162
|
+
#paced_sent = 0;
|
|
163
|
+
|
|
164
|
+
#tokens;
|
|
165
|
+
#last_refill = -1;
|
|
166
|
+
|
|
167
|
+
/** @type {TxStream[]} */
|
|
168
|
+
#tx = [];
|
|
169
|
+
|
|
170
|
+
// unreliable queue for the next flush
|
|
171
|
+
#uq_bytes = new Uint8Array(2048);
|
|
172
|
+
#uq_used = 0;
|
|
173
|
+
#uq_count = 0;
|
|
174
|
+
#uq_offset = new Int32Array(32);
|
|
175
|
+
#uq_length = new Int32Array(32);
|
|
176
|
+
#uq_token = new Int32Array(32);
|
|
177
|
+
|
|
178
|
+
// datagram being built
|
|
179
|
+
#dgram;
|
|
180
|
+
#dgram_len = 0;
|
|
181
|
+
#dgram_open = false;
|
|
182
|
+
#dgram_pn = 0;
|
|
183
|
+
#dgram_flags = 0;
|
|
184
|
+
#dgram_ack_eliciting = false;
|
|
185
|
+
#dgram_rec_start = 0;
|
|
186
|
+
#dgram_ack_largest = -1;
|
|
187
|
+
#flush_sent_eliciting = false;
|
|
188
|
+
#flush_sent_any = false;
|
|
189
|
+
|
|
190
|
+
// ---------------------------------------------------------------- receive side
|
|
191
|
+
|
|
192
|
+
/** received packet numbers at or above {@link #rx_floor} */
|
|
193
|
+
#rx_ranges = new RangeSet(64);
|
|
194
|
+
/** packets below this are dropped: duplicates, or too old to matter */
|
|
195
|
+
#rx_floor = 0;
|
|
196
|
+
#largest_rx = -1;
|
|
197
|
+
#largest_rx_time = 0;
|
|
198
|
+
/** an ack-eliciting packet arrived since the last ACK went out */
|
|
199
|
+
#ack_pending = false;
|
|
200
|
+
|
|
201
|
+
/** @type {RxStream[]} */
|
|
202
|
+
#rx = [];
|
|
203
|
+
|
|
204
|
+
#cursor = { position: 0 };
|
|
205
|
+
#message_out = new Float64Array(1);
|
|
206
|
+
#peek_out = new Float64Array(2);
|
|
207
|
+
/** parsed ACK ranges of the packet being read, [high, low] inclusive pairs */
|
|
208
|
+
#ack_scratch = new Float64Array(2 * MAX_ACK_RANGES);
|
|
209
|
+
|
|
210
|
+
// Fates of unreliable messages, told once the walk that settled them is over: a handler may
|
|
211
|
+
// send, flush or dispose, and none of that may happen to the tables while they are being walked.
|
|
212
|
+
#notice_token = new Int32Array(64);
|
|
213
|
+
/** 1 acknowledged, 0 lost */
|
|
214
|
+
#notice_acked = new Uint8Array(64);
|
|
215
|
+
#notice_count = 0;
|
|
216
|
+
#notice_head = 0;
|
|
217
|
+
|
|
218
|
+
#disposed = false;
|
|
219
|
+
|
|
220
|
+
// ---------------------------------------------------------------- statistics
|
|
221
|
+
|
|
222
|
+
#stats = {
|
|
223
|
+
packets_sent: 0,
|
|
224
|
+
packets_received: 0,
|
|
225
|
+
packets_lost: 0,
|
|
226
|
+
packets_dropped: 0,
|
|
227
|
+
bytes_sent: 0,
|
|
228
|
+
bytes_received: 0,
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* @param {{
|
|
233
|
+
* transport: { send(bytes: Uint8Array, length: number): void, onReceive: Signal, max_datagram_bytes?: number },
|
|
234
|
+
* clock: function(): number,
|
|
235
|
+
* send_rate_bytes_per_second: number,
|
|
236
|
+
* max_message_bytes: number,
|
|
237
|
+
* receive_window_bytes: number,
|
|
238
|
+
* max_queued_bytes: number,
|
|
239
|
+
* max_ack_delay_ms: number,
|
|
240
|
+
* max_ack_ranges?: number,
|
|
241
|
+
* }} options
|
|
242
|
+
* `clock` returns milliseconds and never runs backwards. `send_rate_bytes_per_second` paces
|
|
243
|
+
* the BULK lane. `max_message_bytes` is the largest reliable message either side may send;
|
|
244
|
+
* both ends must agree. `receive_window_bytes` bounds what each reliable lane may have in
|
|
245
|
+
* flight past its acknowledged prefix, and so what a receiver holds out of order. Both ends
|
|
246
|
+
* must agree on these two; a peer that exceeds them is a protocol error.
|
|
247
|
+
* `max_queued_bytes` caps what one lane may hold unacknowledged: past it,
|
|
248
|
+
* {@link send_reliable} throws rather than grow without bound.
|
|
249
|
+
* `max_ack_delay_ms` is how long this side may sit on an ACK and the resolution of its
|
|
250
|
+
* clock: its tick period. `max_ack_ranges` is how many ranges this side's ACKs report, at
|
|
251
|
+
* most 64.
|
|
252
|
+
*
|
|
253
|
+
* A transport that is itself reliable (`transport.reliable`, e.g. a WebSocket) delivers
|
|
254
|
+
* every packet: nothing is declared lost and nothing is probed, or a stalled TCP stream
|
|
255
|
+
* would be fed duplicates behind the originals.
|
|
256
|
+
*/
|
|
257
|
+
constructor({
|
|
258
|
+
transport,
|
|
259
|
+
clock,
|
|
260
|
+
send_rate_bytes_per_second,
|
|
261
|
+
max_message_bytes,
|
|
262
|
+
receive_window_bytes,
|
|
263
|
+
max_queued_bytes,
|
|
264
|
+
max_ack_delay_ms,
|
|
265
|
+
max_ack_ranges = 32,
|
|
266
|
+
}) {
|
|
267
|
+
assert.ok(transport && typeof transport.send === 'function', 'transport must implement send()');
|
|
268
|
+
assert.ok(transport.onReceive, 'transport must expose onReceive');
|
|
269
|
+
assert.isFunction(clock, 'clock');
|
|
270
|
+
assert.isPositiveInteger(send_rate_bytes_per_second, 'send_rate_bytes_per_second');
|
|
271
|
+
assert.isPositiveInteger(max_message_bytes, 'max_message_bytes');
|
|
272
|
+
assert.isPositiveInteger(receive_window_bytes, 'receive_window_bytes');
|
|
273
|
+
assert.isPositiveInteger(max_queued_bytes, 'max_queued_bytes');
|
|
274
|
+
assert.isNumber(max_ack_delay_ms, 'max_ack_delay_ms');
|
|
275
|
+
assert.greaterThanOrEqual(max_ack_delay_ms, 0, 'max_ack_delay_ms');
|
|
276
|
+
assert.isPositiveInteger(max_ack_ranges, 'max_ack_ranges');
|
|
277
|
+
assert.lessThanOrEqual(max_ack_ranges, MAX_ACK_RANGES, 'max_ack_ranges');
|
|
278
|
+
|
|
279
|
+
const max_datagram = transport.max_datagram_bytes ?? 1200;
|
|
280
|
+
assert.isPositiveInteger(max_datagram, 'transport.max_datagram_bytes');
|
|
281
|
+
if (max_datagram < 64 || max_datagram > 16383) {
|
|
282
|
+
throw new RangeError(`Connection: transport.max_datagram_bytes ${max_datagram} must be in [64, 16383]`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
this.#transport = transport;
|
|
286
|
+
this.#clock = clock;
|
|
287
|
+
this.#max_datagram = max_datagram;
|
|
288
|
+
this.#rate_bytes_per_ms = send_rate_bytes_per_second / 1000;
|
|
289
|
+
this.#max_ack_ranges = max_ack_ranges;
|
|
290
|
+
this.#max_ack_delay_ms = max_ack_delay_ms;
|
|
291
|
+
this.#granularity_ms = Math.max(max_ack_delay_ms, 1);
|
|
292
|
+
this.#lossless = transport.reliable === true;
|
|
293
|
+
this.#max_queued_bytes = max_queued_bytes;
|
|
294
|
+
// sends happen once a tick, so the bucket holds two ticks of rate, and never less than two
|
|
295
|
+
// datagrams
|
|
296
|
+
this.#burst_bytes = Math.max(this.#rate_bytes_per_ms * 2 * this.#granularity_ms, 2 * max_datagram);
|
|
297
|
+
this.#tokens = this.#burst_bytes;
|
|
298
|
+
|
|
299
|
+
/** @type {number} @readonly */
|
|
300
|
+
this.max_message_bytes = max_message_bytes;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Largest unreliable message: what fits one datagram after the packet and frame headers.
|
|
304
|
+
* @type {number} @readonly
|
|
305
|
+
*/
|
|
306
|
+
this.max_unreliable_message_bytes = max_datagram - PACKET_HEADER_MAX - MESSAGE_FRAME_HEADER_MAX;
|
|
307
|
+
|
|
308
|
+
for (let lane = 0; lane < LANE_COUNT; lane++) {
|
|
309
|
+
this.#tx.push(new TxStream(receive_window_bytes));
|
|
310
|
+
this.#rx.push(new RxStream(max_message_bytes, receive_window_bytes));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
this.#dgram = new Uint8Array(max_datagram);
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* A message arrived: `(bytes, offset, length)`. `bytes` is the connection's or the
|
|
317
|
+
* transport's buffer, valid for the duration of the call only.
|
|
318
|
+
* @type {Signal}
|
|
319
|
+
*/
|
|
320
|
+
this.onMessage = new Signal();
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* An unreliable message sent with a token arrived: `(token)`.
|
|
324
|
+
* @type {Signal}
|
|
325
|
+
*/
|
|
326
|
+
this.onMessageAcked = new Signal();
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* An unreliable message sent with a token was lost: `(token)`. Lost means not confirmed:
|
|
330
|
+
* a message whose packet arrived but whose acknowledgement never got through — every ACK
|
|
331
|
+
* that could report it lost, or crowded out by newer ranges — is reported lost, as QUIC
|
|
332
|
+
* does.
|
|
333
|
+
* @type {Signal}
|
|
334
|
+
*/
|
|
335
|
+
this.onMessageLost = new Signal();
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* A datagram that does not parse, or is of another protocol version, was dropped whole and
|
|
339
|
+
* unacknowledged: `(reason)`. The connection carries on; anyone can send a stray datagram.
|
|
340
|
+
* @type {Signal}
|
|
341
|
+
*/
|
|
342
|
+
this.onMalformedDatagram = new Signal();
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* The connection is no longer whole: `(reason)`. The peer broke the protocol on a reliable
|
|
346
|
+
* lane — a message longer than `max_message_bytes`, bytes past the receive window, more
|
|
347
|
+
* holes than a sender keeping to its window makes — and the lane has stopped, so nothing
|
|
348
|
+
* more will arrive on it; or the peer acknowledged a packet this side never sent, so it
|
|
349
|
+
* took in a datagram that was not this side's and nothing it acknowledges can be trusted.
|
|
350
|
+
* The datagram carrying that ACK is dropped, as is every later one that repeats it.
|
|
351
|
+
*
|
|
352
|
+
* The connection does not authenticate datagrams: its transport must deliver only the
|
|
353
|
+
* peer's (DTLS and TLS do; a UDP socket filters by source address). The cure is a new
|
|
354
|
+
* connection.
|
|
355
|
+
* @type {Signal}
|
|
356
|
+
*/
|
|
357
|
+
this.onProtocolError = new Signal();
|
|
358
|
+
|
|
359
|
+
transport.onReceive.add(this.#receive, this);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ================================================================ public: sending
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Queue an unreliable message for the next {@link flush}. With `token >= 0` the connection
|
|
366
|
+
* reports its fate: {@link onMessageAcked} once the packet carrying it is acknowledged, or
|
|
367
|
+
* {@link onMessageLost} once it is declared lost — exactly one of them.
|
|
368
|
+
*
|
|
369
|
+
* @param {Uint8Array} bytes
|
|
370
|
+
* @param {number} offset
|
|
371
|
+
* @param {number} length at most {@link max_unreliable_message_bytes}
|
|
372
|
+
* @param {number} token caller's id for the notice, or -1 for none
|
|
373
|
+
*/
|
|
374
|
+
send_unreliable(bytes, offset, length, token) {
|
|
375
|
+
if (length > this.max_unreliable_message_bytes) {
|
|
376
|
+
throw new RangeError(`Connection.send_unreliable: ${length} bytes exceeds the ${this.max_unreliable_message_bytes}-byte datagram limit; send it on a reliable lane`);
|
|
377
|
+
}
|
|
378
|
+
const n = this.#uq_count;
|
|
379
|
+
if (n === this.#uq_offset.length) this.#grow_unreliable_queue();
|
|
380
|
+
if (this.#uq_used + length > this.#uq_bytes.length) {
|
|
381
|
+
let size = this.#uq_bytes.length * 2;
|
|
382
|
+
while (size < this.#uq_used + length) size *= 2;
|
|
383
|
+
const next = new Uint8Array(size);
|
|
384
|
+
next.set(this.#uq_bytes.subarray(0, this.#uq_used));
|
|
385
|
+
this.#uq_bytes = next;
|
|
386
|
+
}
|
|
387
|
+
bytes_copy(bytes, offset, this.#uq_bytes, this.#uq_used, length);
|
|
388
|
+
this.#uq_offset[n] = this.#uq_used;
|
|
389
|
+
this.#uq_length[n] = length;
|
|
390
|
+
this.#uq_token[n] = token;
|
|
391
|
+
this.#uq_used += length;
|
|
392
|
+
this.#uq_count = n + 1;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Queue a reliable message on `lane`. It arrives, whole and in order with the lane's other
|
|
397
|
+
* messages, unless the connection ends first.
|
|
398
|
+
*
|
|
399
|
+
* @param {number} lane one of {@link Lane}
|
|
400
|
+
* @param {Uint8Array} bytes
|
|
401
|
+
* @param {number} offset
|
|
402
|
+
* @param {number} length at most {@link max_message_bytes}
|
|
403
|
+
* @returns {number} delivery mark: see {@link is_delivered}
|
|
404
|
+
*/
|
|
405
|
+
send_reliable(lane, bytes, offset, length) {
|
|
406
|
+
if (length > this.max_message_bytes) {
|
|
407
|
+
throw new RangeError(`Connection.send_reliable: ${length} bytes exceeds max_message_bytes ${this.max_message_bytes}`);
|
|
408
|
+
}
|
|
409
|
+
const tx = this.#tx[lane];
|
|
410
|
+
if (tx.end - tx.acked_prefix + length > this.#max_queued_bytes) {
|
|
411
|
+
throw new RangeError(`Connection.send_reliable: lane ${lane} already holds ${tx.end - tx.acked_prefix} unacknowledged bytes; ${length} more would pass max_queued_bytes ${this.#max_queued_bytes}`);
|
|
412
|
+
}
|
|
413
|
+
return tx.append(bytes, offset, length);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Whether every message on `lane` up to the one whose mark this is has been acknowledged.
|
|
418
|
+
* @param {number} lane
|
|
419
|
+
* @param {number} mark from {@link send_reliable}
|
|
420
|
+
* @returns {boolean}
|
|
421
|
+
*/
|
|
422
|
+
is_delivered(lane, mark) {
|
|
423
|
+
return this.#tx[lane].acked_prefix >= mark;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Bytes queued on `lane` the peer has not acknowledged.
|
|
428
|
+
* @param {number} lane
|
|
429
|
+
* @returns {number}
|
|
430
|
+
*/
|
|
431
|
+
unacked_bytes(lane) {
|
|
432
|
+
const tx = this.#tx[lane];
|
|
433
|
+
return tx.end - tx.acked_prefix;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Send everything queued that may go now, packed into as few datagrams as fit: the ACK, the
|
|
438
|
+
* CONTROL lane, unreliable messages, then the BULK lane while the token bucket allows. Also
|
|
439
|
+
* runs the loss and probe timers.
|
|
440
|
+
*/
|
|
441
|
+
flush() {
|
|
442
|
+
if (this.#disposed) return;
|
|
443
|
+
const now = this.#clock();
|
|
444
|
+
|
|
445
|
+
this.#detect_lost(now);
|
|
446
|
+
this.#check_probe_timeout(now);
|
|
447
|
+
this.#refill(now);
|
|
448
|
+
|
|
449
|
+
this.#flush_sent_eliciting = false;
|
|
450
|
+
this.#flush_sent_any = false;
|
|
451
|
+
|
|
452
|
+
this.#paced_sent = 0;
|
|
453
|
+
this.#send_stream(Lane.CONTROL, now);
|
|
454
|
+
this.#send_unreliable_queue(now);
|
|
455
|
+
this.#send_stream(Lane.FRAMES, now);
|
|
456
|
+
this.#send_stream(Lane.USER, now);
|
|
457
|
+
this.#send_stream(Lane.BULK, now);
|
|
458
|
+
this.#probe_credit = false;
|
|
459
|
+
|
|
460
|
+
if (this.#probe_pending && !this.#flush_sent_eliciting && !this.#dgram_ack_eliciting) {
|
|
461
|
+
this.#ensure_room(1, now);
|
|
462
|
+
this.#dgram[this.#dgram_len++] = FRAME_PING;
|
|
463
|
+
this.#dgram_ack_eliciting = true;
|
|
464
|
+
}
|
|
465
|
+
this.#probe_pending = false;
|
|
466
|
+
|
|
467
|
+
if (this.#ack_pending && !this.#dgram_open && !this.#flush_sent_any) {
|
|
468
|
+
// An ACK with nothing else to carry it. Once a round trip it asks for an ACK itself: a
|
|
469
|
+
// side that only ever acknowledges never hears which of its ACKs arrived, so it could
|
|
470
|
+
// never stop reporting old ranges (RFC 9000 §13.2.4).
|
|
471
|
+
this.#open_packet(now);
|
|
472
|
+
if (now - this.#last_ack_eliciting_sent >= this.#smoothed_rtt) {
|
|
473
|
+
this.#dgram[this.#dgram_len++] = FRAME_PING;
|
|
474
|
+
this.#dgram_ack_eliciting = true;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
this.#close_packet(now);
|
|
479
|
+
this.#emit_notices();
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// ================================================================ public: diagnostics
|
|
483
|
+
|
|
484
|
+
/** Smoothed round-trip time, ms; RFC 9002's initial 333 ms until the first sample. */
|
|
485
|
+
get smoothed_rtt() {
|
|
486
|
+
return this.#smoothed_rtt;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/** Packets sent and not yet acknowledged or declared lost that asked for an ACK. */
|
|
490
|
+
get in_flight_count() {
|
|
491
|
+
return this.#in_flight_count;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/** Most bytes one reliable lane may hold unacknowledged; {@link send_reliable} throws past it. */
|
|
495
|
+
get max_queued_bytes() {
|
|
496
|
+
return this.#max_queued_bytes;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* @returns {{packets_sent: number, packets_received: number, packets_lost: number, packets_dropped: number, bytes_sent: number, bytes_received: number}}
|
|
501
|
+
*/
|
|
502
|
+
getStats() {
|
|
503
|
+
return { ...this.#stats };
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Stop: no more receiving, and nothing queued will be sent. Call {@link flush} first for a
|
|
508
|
+
* last send.
|
|
509
|
+
*/
|
|
510
|
+
dispose() {
|
|
511
|
+
if (this.#disposed) return;
|
|
512
|
+
this.#disposed = true;
|
|
513
|
+
this.#transport.onReceive.remove(this.#receive, this);
|
|
514
|
+
this.#uq_count = 0;
|
|
515
|
+
this.#uq_used = 0;
|
|
516
|
+
this.#notice_count = 0;
|
|
517
|
+
this.#notice_head = 0;
|
|
518
|
+
for (let lane = 0; lane < LANE_COUNT; lane++) {
|
|
519
|
+
this.#tx[lane].clear();
|
|
520
|
+
this.#rx[lane].clear();
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// ================================================================ sending internals
|
|
525
|
+
|
|
526
|
+
#refill(now) {
|
|
527
|
+
if (this.#last_refill < 0) {
|
|
528
|
+
this.#last_refill = now;
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
const elapsed = now - this.#last_refill;
|
|
532
|
+
if (elapsed <= 0) return;
|
|
533
|
+
this.#last_refill = now;
|
|
534
|
+
this.#tokens = Math.min(this.#burst_bytes, this.#tokens + elapsed * this.#rate_bytes_per_ms);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Send what `lane` has: re-sends first, then new bytes up to its window. A paced lane stops
|
|
539
|
+
* when the bucket is empty, except that paced lanes always get one datagram's worth a flush (so
|
|
540
|
+
* unpaced traffic cannot starve them) and a probe always goes.
|
|
541
|
+
*/
|
|
542
|
+
#send_stream(lane, now) {
|
|
543
|
+
const tx = this.#tx[lane];
|
|
544
|
+
const paced = LANE_PACED[lane];
|
|
545
|
+
const out = this.#peek_out;
|
|
546
|
+
while (tx.has_sendable()) {
|
|
547
|
+
if (paced && this.#tokens - this.#dgram_len <= 0 && this.#paced_sent >= this.#max_datagram) {
|
|
548
|
+
if (!this.#probe_credit) return;
|
|
549
|
+
this.#probe_credit = false;
|
|
550
|
+
}
|
|
551
|
+
this.#ensure_room(STREAM_FRAME_HEADER_MAX + STREAM_FRAME_MIN_PAYLOAD, now);
|
|
552
|
+
const room = this.#max_datagram - this.#dgram_len - STREAM_FRAME_HEADER_MAX;
|
|
553
|
+
tx.peek(room, out);
|
|
554
|
+
const offset = out[0];
|
|
555
|
+
const length = out[1];
|
|
556
|
+
if (length <= 0) return;
|
|
557
|
+
|
|
558
|
+
const d = this.#dgram;
|
|
559
|
+
let p = this.#dgram_len;
|
|
560
|
+
d[p++] = FRAME_STREAM | lane;
|
|
561
|
+
p = varint_write(d, p, offset);
|
|
562
|
+
p = varint_write(d, p, length);
|
|
563
|
+
tx.copy_out(offset, length, d, p);
|
|
564
|
+
this.#dgram_len = p + length;
|
|
565
|
+
this.#dgram_ack_eliciting = true;
|
|
566
|
+
|
|
567
|
+
tx.mark_sent(offset, length);
|
|
568
|
+
this.#push_record(RECORD_STREAM, lane, offset, length);
|
|
569
|
+
if (paced) this.#paced_sent += length;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
#send_unreliable_queue(now) {
|
|
574
|
+
const n = this.#uq_count;
|
|
575
|
+
for (let i = 0; i < n; i++) {
|
|
576
|
+
const length = this.#uq_length[i];
|
|
577
|
+
this.#ensure_room(1 + varint_size(length) + length, now);
|
|
578
|
+
const d = this.#dgram;
|
|
579
|
+
let p = this.#dgram_len;
|
|
580
|
+
d[p++] = FRAME_MESSAGE;
|
|
581
|
+
p = varint_write(d, p, length);
|
|
582
|
+
const from = this.#uq_offset[i];
|
|
583
|
+
bytes_copy(this.#uq_bytes, from, d, p, length);
|
|
584
|
+
this.#dgram_len = p + length;
|
|
585
|
+
this.#dgram_ack_eliciting = true;
|
|
586
|
+
|
|
587
|
+
const token = this.#uq_token[i];
|
|
588
|
+
if (token >= 0) this.#push_record(RECORD_MESSAGE, token, 0, 0);
|
|
589
|
+
}
|
|
590
|
+
this.#uq_count = 0;
|
|
591
|
+
this.#uq_used = 0;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Make sure the open datagram has `bytes` of room, closing it and opening the next if not.
|
|
596
|
+
*/
|
|
597
|
+
#ensure_room(bytes, now) {
|
|
598
|
+
if (this.#dgram_open && this.#dgram_len + bytes <= this.#max_datagram) return;
|
|
599
|
+
this.#close_packet(now);
|
|
600
|
+
this.#open_packet(now);
|
|
601
|
+
if (this.#dgram_len + bytes > this.#max_datagram) {
|
|
602
|
+
// the ACK that opens a flush's first datagram leaves too little: it goes alone, and the
|
|
603
|
+
// next datagram carries none
|
|
604
|
+
this.#close_packet(now);
|
|
605
|
+
this.#open_packet(now);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
#open_packet(now) {
|
|
610
|
+
const pn = this.#next_pn++;
|
|
611
|
+
this.#dgram_pn = pn;
|
|
612
|
+
this.#dgram_open = true;
|
|
613
|
+
this.#dgram_ack_eliciting = false;
|
|
614
|
+
this.#dgram_rec_start = this.#rec_head;
|
|
615
|
+
this.#dgram_ack_largest = -1;
|
|
616
|
+
|
|
617
|
+
// 2 bytes while the receiver can still expand it: RFC 9000 §17.1
|
|
618
|
+
const unacked = pn - this.#largest_acked;
|
|
619
|
+
const long = unacked >= 16384;
|
|
620
|
+
this.#dgram_flags = long ? FLAG_PN32 : 0;
|
|
621
|
+
const d = this.#dgram;
|
|
622
|
+
let p = 1;
|
|
623
|
+
if (long) {
|
|
624
|
+
d[p++] = (pn >>> 24) & 0xFF;
|
|
625
|
+
d[p++] = (pn >>> 16) & 0xFF;
|
|
626
|
+
}
|
|
627
|
+
d[p++] = (pn >>> 8) & 0xFF;
|
|
628
|
+
d[p++] = pn & 0xFF;
|
|
629
|
+
this.#dgram_len = p;
|
|
630
|
+
|
|
631
|
+
// the first datagram of a flush acknowledges what has been received
|
|
632
|
+
if (!this.#rx_ranges.is_empty() && !this.#flush_sent_any) {
|
|
633
|
+
this.#write_ack(now);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
#write_ack(now) {
|
|
638
|
+
const ranges = this.#rx_ranges;
|
|
639
|
+
const top = ranges.count - 1;
|
|
640
|
+
const largest = ranges.end(top) - 1;
|
|
641
|
+
const delay_ms = Math.max(0, now - this.#largest_rx_time);
|
|
642
|
+
const delay = Math.min(Math.round(delay_ms * ACK_DELAY_UNITS_PER_MS), 1073741823);
|
|
643
|
+
const first = largest - ranges.start(top);
|
|
644
|
+
|
|
645
|
+
// As many ranges as fit half the datagram, newest first: the rest of it is for frames. The
|
|
646
|
+
// ranges left out are older; the peer learns of them from a later ACK, or declares them lost.
|
|
647
|
+
const room = ((this.#max_datagram - PACKET_HEADER_MAX) >> 1) - this.#dgram_len;
|
|
648
|
+
let size = varint_size(largest) + varint_size(delay) + 1 + varint_size(first);
|
|
649
|
+
let reported = 1;
|
|
650
|
+
{
|
|
651
|
+
let previous_start = ranges.start(top);
|
|
652
|
+
const most = Math.min(ranges.count, this.#max_ack_ranges);
|
|
653
|
+
for (let i = top - 1; reported < most; i--, reported++) {
|
|
654
|
+
const s = ranges.start(i);
|
|
655
|
+
const e = ranges.end(i);
|
|
656
|
+
const more = varint_size(previous_start - e - 1) + varint_size(e - 1 - s);
|
|
657
|
+
if (size + more > room) break;
|
|
658
|
+
size += more;
|
|
659
|
+
previous_start = s;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
const d = this.#dgram;
|
|
664
|
+
let p = this.#dgram_len;
|
|
665
|
+
p = varint_write(d, p, largest);
|
|
666
|
+
p = varint_write(d, p, delay);
|
|
667
|
+
p = varint_write(d, p, reported - 1);
|
|
668
|
+
p = varint_write(d, p, first);
|
|
669
|
+
let previous_start = ranges.start(top);
|
|
670
|
+
for (let i = top - 1; i > top - reported; i--) {
|
|
671
|
+
const s = ranges.start(i);
|
|
672
|
+
const e = ranges.end(i);
|
|
673
|
+
p = varint_write(d, p, previous_start - e - 1);
|
|
674
|
+
p = varint_write(d, p, e - 1 - s);
|
|
675
|
+
previous_start = s;
|
|
676
|
+
}
|
|
677
|
+
this.#dgram_len = p;
|
|
678
|
+
this.#dgram_flags |= FLAG_ACK;
|
|
679
|
+
this.#dgram_ack_largest = largest;
|
|
680
|
+
this.#ack_pending = false;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
#close_packet(now) {
|
|
684
|
+
if (!this.#dgram_open) return;
|
|
685
|
+
this.#dgram_open = false;
|
|
686
|
+
const d = this.#dgram;
|
|
687
|
+
d[0] = this.#dgram_flags | (PROTOCOL_VERSION << 4);
|
|
688
|
+
const length = this.#dgram_len;
|
|
689
|
+
this.#transport.send(d, length);
|
|
690
|
+
|
|
691
|
+
this.#flush_sent_any = true;
|
|
692
|
+
// unpaced traffic may take the bucket below zero, never more than a burst below
|
|
693
|
+
this.#tokens = Math.max(this.#tokens - length, -this.#burst_bytes);
|
|
694
|
+
this.#stats.packets_sent++;
|
|
695
|
+
this.#stats.bytes_sent += length;
|
|
696
|
+
|
|
697
|
+
if (!this.#dgram_ack_eliciting) return;
|
|
698
|
+
this.#flush_sent_eliciting = true;
|
|
699
|
+
|
|
700
|
+
const pn = this.#dgram_pn;
|
|
701
|
+
this.#ensure_packet_capacity(pn);
|
|
702
|
+
const slot = pn & (this.#pkt_capacity - 1);
|
|
703
|
+
this.#pkt_pn[slot] = pn;
|
|
704
|
+
this.#pkt_sent_time[slot] = now;
|
|
705
|
+
this.#pkt_size[slot] = length;
|
|
706
|
+
this.#pkt_rec_start[slot] = this.#dgram_rec_start;
|
|
707
|
+
this.#pkt_rec_count[slot] = this.#rec_head - this.#dgram_rec_start;
|
|
708
|
+
this.#pkt_ack_largest[slot] = this.#dgram_ack_largest;
|
|
709
|
+
this.#in_flight_count++;
|
|
710
|
+
this.#last_ack_eliciting_sent = now;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
#push_record(kind, id, offset, length) {
|
|
714
|
+
const oldest = this.#oldest_record_in_use();
|
|
715
|
+
if (this.#rec_head - oldest >= this.#rec_capacity) this.#grow_records(oldest);
|
|
716
|
+
const i = this.#rec_head % this.#rec_capacity;
|
|
717
|
+
this.#rec_kind[i] = kind;
|
|
718
|
+
this.#rec_id[i] = id;
|
|
719
|
+
this.#rec_offset[i] = offset;
|
|
720
|
+
this.#rec_length[i] = length;
|
|
721
|
+
this.#rec_head++;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/** Absolute index of the oldest record a packet still in flight (or being built) may own. */
|
|
725
|
+
#oldest_record_in_use() {
|
|
726
|
+
if (this.#in_flight_count > 0) {
|
|
727
|
+
for (let pn = this.#oldest_unretired; pn < this.#next_pn; pn++) {
|
|
728
|
+
const slot = pn & (this.#pkt_capacity - 1);
|
|
729
|
+
if (this.#pkt_pn[slot] === pn) return this.#pkt_rec_start[slot];
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
return this.#dgram_open ? this.#dgram_rec_start : this.#rec_head;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
#grow_records(oldest) {
|
|
736
|
+
const old_capacity = this.#rec_capacity;
|
|
737
|
+
const capacity = old_capacity * 2;
|
|
738
|
+
const kind = new Uint8Array(capacity);
|
|
739
|
+
const id = new Int32Array(capacity);
|
|
740
|
+
const offset = new Float64Array(capacity);
|
|
741
|
+
const length = new Int32Array(capacity);
|
|
742
|
+
for (let r = oldest; r < this.#rec_head; r++) {
|
|
743
|
+
const from = r % old_capacity;
|
|
744
|
+
const to = r % capacity;
|
|
745
|
+
kind[to] = this.#rec_kind[from];
|
|
746
|
+
id[to] = this.#rec_id[from];
|
|
747
|
+
offset[to] = this.#rec_offset[from];
|
|
748
|
+
length[to] = this.#rec_length[from];
|
|
749
|
+
}
|
|
750
|
+
this.#rec_capacity = capacity;
|
|
751
|
+
this.#rec_kind = kind;
|
|
752
|
+
this.#rec_id = id;
|
|
753
|
+
this.#rec_offset = offset;
|
|
754
|
+
this.#rec_length = length;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
#ensure_packet_capacity(pn) {
|
|
758
|
+
while (pn - this.#oldest_unretired >= this.#pkt_capacity) {
|
|
759
|
+
if (this.#pkt_capacity >= MAX_IN_FLIGHT) {
|
|
760
|
+
// the peer has gone quiet for longer than any link holds packets: give the oldest up
|
|
761
|
+
this.#retire_lost(this.#oldest_unretired);
|
|
762
|
+
// never past `pn`: it is the packet being recorded, not yet in the table
|
|
763
|
+
this.#advance_oldest_unretired(pn);
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
this.#grow_packets();
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
#grow_packets() {
|
|
771
|
+
const old_capacity = this.#pkt_capacity;
|
|
772
|
+
const capacity = old_capacity * 2;
|
|
773
|
+
const pn_ = new Float64Array(capacity).fill(-1);
|
|
774
|
+
const sent = new Float64Array(capacity);
|
|
775
|
+
const size = new Uint16Array(capacity);
|
|
776
|
+
const rec_start = new Float64Array(capacity);
|
|
777
|
+
const rec_count = new Uint16Array(capacity);
|
|
778
|
+
const ack_largest = new Float64Array(capacity);
|
|
779
|
+
for (let i = 0; i < old_capacity; i++) {
|
|
780
|
+
const pn = this.#pkt_pn[i];
|
|
781
|
+
if (pn < 0) continue;
|
|
782
|
+
const to = pn % capacity;
|
|
783
|
+
pn_[to] = pn;
|
|
784
|
+
sent[to] = this.#pkt_sent_time[i];
|
|
785
|
+
size[to] = this.#pkt_size[i];
|
|
786
|
+
rec_start[to] = this.#pkt_rec_start[i];
|
|
787
|
+
rec_count[to] = this.#pkt_rec_count[i];
|
|
788
|
+
ack_largest[to] = this.#pkt_ack_largest[i];
|
|
789
|
+
}
|
|
790
|
+
this.#pkt_capacity = capacity;
|
|
791
|
+
this.#pkt_pn = pn_;
|
|
792
|
+
this.#pkt_sent_time = sent;
|
|
793
|
+
this.#pkt_size = size;
|
|
794
|
+
this.#pkt_rec_start = rec_start;
|
|
795
|
+
this.#pkt_rec_count = rec_count;
|
|
796
|
+
this.#pkt_ack_largest = ack_largest;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// ================================================================ loss, RTT, probe
|
|
800
|
+
|
|
801
|
+
#loss_delay() {
|
|
802
|
+
const rtt = this.#has_rtt ? Math.max(this.#latest_rtt, this.#smoothed_rtt) : INITIAL_RTT_MS;
|
|
803
|
+
return Math.max(rtt * 9 / 8, this.#granularity_ms);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* RFC 9002 §6.1: a packet is lost once a packet {@link PACKET_THRESHOLD} later is acknowledged,
|
|
808
|
+
* or once it is older than the loss delay and something sent after it has been acknowledged.
|
|
809
|
+
*/
|
|
810
|
+
#detect_lost(now) {
|
|
811
|
+
const largest = this.#largest_acked;
|
|
812
|
+
if (this.#lossless || largest < 0 || this.#in_flight_count === 0) return;
|
|
813
|
+
const lost_before = now - this.#loss_delay();
|
|
814
|
+
const mask = this.#pkt_capacity - 1;
|
|
815
|
+
const last = Math.min(largest - 1, this.#next_pn - 1);
|
|
816
|
+
for (let pn = this.#oldest_unretired; pn <= last; pn++) {
|
|
817
|
+
const slot = pn & mask;
|
|
818
|
+
if (this.#pkt_pn[slot] !== pn) continue;
|
|
819
|
+
if (largest - pn >= PACKET_THRESHOLD || this.#pkt_sent_time[slot] <= lost_before) {
|
|
820
|
+
this.#retire_lost(pn);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
this.#advance_oldest_unretired();
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* RFC 9002 §6.2: with ack-eliciting packets outstanding and no ACK for a probe timeout, send
|
|
828
|
+
* the oldest outstanding reliable bytes again (or a PING when only unreliable messages are
|
|
829
|
+
* outstanding) to draw an ACK. Backs off by doubling.
|
|
830
|
+
*/
|
|
831
|
+
#check_probe_timeout(now) {
|
|
832
|
+
if (this.#lossless || this.#in_flight_count === 0) {
|
|
833
|
+
this.#pto_count = 0;
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
const pto = (this.#smoothed_rtt + Math.max(4 * this.#rttvar, this.#granularity_ms) + this.#max_ack_delay_ms)
|
|
837
|
+
* (1 << Math.min(this.#pto_count, 16));
|
|
838
|
+
if (now - this.#last_ack_eliciting_sent < pto) return;
|
|
839
|
+
|
|
840
|
+
this.#pto_count++;
|
|
841
|
+
this.#probe_credit = true;
|
|
842
|
+
const mask = this.#pkt_capacity - 1;
|
|
843
|
+
for (let pn = this.#oldest_unretired; pn < this.#next_pn; pn++) {
|
|
844
|
+
const slot = pn & mask;
|
|
845
|
+
if (this.#pkt_pn[slot] !== pn) continue;
|
|
846
|
+
if (this.#requeue_stream_records(slot)) return;
|
|
847
|
+
}
|
|
848
|
+
this.#probe_pending = true;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
/**
|
|
852
|
+
* Queue the reliable bytes a packet carried for re-sending, leaving the packet in flight.
|
|
853
|
+
* @returns {boolean} whether any of them is still unacknowledged: a packet whose bytes were
|
|
854
|
+
* all acknowledged by another (an earlier probe's, or the one it re-sent) has nothing to
|
|
855
|
+
* probe with
|
|
856
|
+
*/
|
|
857
|
+
#requeue_stream_records(slot) {
|
|
858
|
+
const start = this.#pkt_rec_start[slot];
|
|
859
|
+
const count = this.#pkt_rec_count[slot];
|
|
860
|
+
let any = false;
|
|
861
|
+
for (let r = start; r < start + count; r++) {
|
|
862
|
+
const i = r % this.#rec_capacity;
|
|
863
|
+
if (this.#rec_kind[i] !== RECORD_STREAM) continue;
|
|
864
|
+
if (this.#tx[this.#rec_id[i]].on_lost(this.#rec_offset[i], this.#rec_length[i])) any = true;
|
|
865
|
+
}
|
|
866
|
+
return any;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
#retire_lost(pn) {
|
|
870
|
+
const slot = pn & (this.#pkt_capacity - 1);
|
|
871
|
+
if (this.#pkt_pn[slot] !== pn) return;
|
|
872
|
+
this.#pkt_pn[slot] = -1;
|
|
873
|
+
this.#in_flight_count--;
|
|
874
|
+
this.#stats.packets_lost++;
|
|
875
|
+
|
|
876
|
+
const start = this.#pkt_rec_start[slot];
|
|
877
|
+
const count = this.#pkt_rec_count[slot];
|
|
878
|
+
for (let r = start; r < start + count; r++) {
|
|
879
|
+
const i = r % this.#rec_capacity;
|
|
880
|
+
const kind = this.#rec_kind[i];
|
|
881
|
+
if (kind === RECORD_STREAM) {
|
|
882
|
+
this.#tx[this.#rec_id[i]].on_lost(this.#rec_offset[i], this.#rec_length[i]);
|
|
883
|
+
} else if (kind === RECORD_MESSAGE) {
|
|
884
|
+
this.#queue_notice(this.#rec_id[i], 0);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
|
+
* @param {number} token
|
|
891
|
+
* @param {number} acked 1 acknowledged, 0 lost
|
|
892
|
+
*/
|
|
893
|
+
#queue_notice(token, acked) {
|
|
894
|
+
const n = this.#notice_count;
|
|
895
|
+
if (n === this.#notice_token.length) {
|
|
896
|
+
const token_next = new Int32Array(n * 2);
|
|
897
|
+
const acked_next = new Uint8Array(n * 2);
|
|
898
|
+
token_next.set(this.#notice_token);
|
|
899
|
+
acked_next.set(this.#notice_acked);
|
|
900
|
+
this.#notice_token = token_next;
|
|
901
|
+
this.#notice_acked = acked_next;
|
|
902
|
+
}
|
|
903
|
+
this.#notice_token[n] = token;
|
|
904
|
+
this.#notice_acked[n] = acked;
|
|
905
|
+
this.#notice_count = n + 1;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* Tell the queued fates, in order. A handler may flush — which tells the rest, and its own —
|
|
910
|
+
* or dispose, after which nothing more is told.
|
|
911
|
+
*/
|
|
912
|
+
#emit_notices() {
|
|
913
|
+
while (this.#notice_head < this.#notice_count && !this.#disposed) {
|
|
914
|
+
const i = this.#notice_head++;
|
|
915
|
+
const token = this.#notice_token[i];
|
|
916
|
+
if (this.#notice_acked[i] !== 0) {
|
|
917
|
+
this.onMessageAcked.send1(token);
|
|
918
|
+
} else {
|
|
919
|
+
this.onMessageLost.send1(token);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
this.#notice_head = 0;
|
|
923
|
+
this.#notice_count = 0;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
#retire_acked(pn) {
|
|
927
|
+
const slot = pn & (this.#pkt_capacity - 1);
|
|
928
|
+
this.#pkt_pn[slot] = -1;
|
|
929
|
+
this.#in_flight_count--;
|
|
930
|
+
|
|
931
|
+
// the peer has seen our ACK up to this: it need not hear of those packets again
|
|
932
|
+
const reported = this.#pkt_ack_largest[slot];
|
|
933
|
+
if (reported >= 0 && reported + 1 > this.#rx_floor) {
|
|
934
|
+
this.#rx_floor = reported + 1;
|
|
935
|
+
this.#rx_ranges.remove_below(this.#rx_floor);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
const start = this.#pkt_rec_start[slot];
|
|
939
|
+
const count = this.#pkt_rec_count[slot];
|
|
940
|
+
for (let r = start; r < start + count; r++) {
|
|
941
|
+
const i = r % this.#rec_capacity;
|
|
942
|
+
const kind = this.#rec_kind[i];
|
|
943
|
+
if (kind === RECORD_STREAM) {
|
|
944
|
+
this.#tx[this.#rec_id[i]].on_acked(this.#rec_offset[i], this.#rec_length[i]);
|
|
945
|
+
} else if (kind === RECORD_MESSAGE) {
|
|
946
|
+
this.#queue_notice(this.#rec_id[i], 1);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
/**
|
|
952
|
+
* Move the oldest-unretired mark up to the oldest packet still in flight, or to `limit`.
|
|
953
|
+
* @param {number} [limit]
|
|
954
|
+
*/
|
|
955
|
+
#advance_oldest_unretired(limit = this.#next_pn) {
|
|
956
|
+
const mask = this.#pkt_capacity - 1;
|
|
957
|
+
let pn = this.#oldest_unretired;
|
|
958
|
+
while (pn < limit && this.#pkt_pn[pn & mask] !== pn) pn++;
|
|
959
|
+
this.#oldest_unretired = pn;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
#update_rtt(latest, ack_delay) {
|
|
963
|
+
this.#latest_rtt = latest;
|
|
964
|
+
if (!this.#has_rtt) {
|
|
965
|
+
this.#has_rtt = true;
|
|
966
|
+
this.#min_rtt = latest;
|
|
967
|
+
this.#smoothed_rtt = latest;
|
|
968
|
+
this.#rttvar = latest / 2;
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
this.#min_rtt = Math.min(this.#min_rtt, latest);
|
|
972
|
+
const delay = Math.min(ack_delay, this.#max_ack_delay_ms);
|
|
973
|
+
const adjusted = latest >= this.#min_rtt + delay ? latest - delay : latest;
|
|
974
|
+
this.#rttvar = 0.75 * this.#rttvar + 0.25 * Math.abs(this.#smoothed_rtt - adjusted);
|
|
975
|
+
this.#smoothed_rtt = 0.875 * this.#smoothed_rtt + 0.125 * adjusted;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// ================================================================ receiving
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* @param {Uint8Array} bytes
|
|
982
|
+
* @param {number} length
|
|
983
|
+
*/
|
|
984
|
+
#receive(bytes, length) {
|
|
985
|
+
if (this.#disposed) return;
|
|
986
|
+
const now = this.#clock();
|
|
987
|
+
this.#stats.bytes_received += length;
|
|
988
|
+
|
|
989
|
+
if (length < 3) {
|
|
990
|
+
this.#drop('datagram shorter than a packet header');
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
const flags = bytes[0];
|
|
994
|
+
if ((flags >>> 4) !== PROTOCOL_VERSION) {
|
|
995
|
+
this.#drop(`protocol version ${flags >>> 4}, expected ${PROTOCOL_VERSION}`);
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
if ((flags & ~FLAGS_KNOWN) !== 0) {
|
|
999
|
+
this.#drop('unknown flags');
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
let p = 1;
|
|
1003
|
+
let truncated;
|
|
1004
|
+
let bits;
|
|
1005
|
+
if ((flags & FLAG_PN32) !== 0) {
|
|
1006
|
+
if (length < 5) {
|
|
1007
|
+
this.#drop('datagram shorter than its packet number');
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
truncated = ((bytes[1] << 24) >>> 0) + (bytes[2] << 16) + (bytes[3] << 8) + bytes[4];
|
|
1011
|
+
bits = 32;
|
|
1012
|
+
p = 5;
|
|
1013
|
+
} else {
|
|
1014
|
+
truncated = (bytes[1] << 8) | bytes[2];
|
|
1015
|
+
bits = 16;
|
|
1016
|
+
p = 3;
|
|
1017
|
+
}
|
|
1018
|
+
const pn = this.#expand_packet_number(truncated, bits);
|
|
1019
|
+
|
|
1020
|
+
if (pn < this.#rx_floor || this.#rx_ranges.contains(pn)) {
|
|
1021
|
+
this.#stats.packets_dropped++;
|
|
1022
|
+
return; // a duplicate, or too old to matter
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
// Pass 1: the whole packet must parse before any of it is acted on.
|
|
1026
|
+
const ack_end = this.#validate(bytes, p, length, flags);
|
|
1027
|
+
if (ack_end < 0) return;
|
|
1028
|
+
|
|
1029
|
+
this.#stats.packets_received++;
|
|
1030
|
+
this.#rx_ranges.add(pn, pn + 1);
|
|
1031
|
+
if (pn > this.#largest_rx) {
|
|
1032
|
+
this.#largest_rx = pn;
|
|
1033
|
+
this.#largest_rx_time = now;
|
|
1034
|
+
}
|
|
1035
|
+
if (this.#rx_ranges.count > this.#max_ack_ranges) {
|
|
1036
|
+
this.#rx_ranges.keep_highest(this.#max_ack_ranges);
|
|
1037
|
+
this.#rx_floor = Math.max(this.#rx_floor, this.#rx_ranges.min());
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
// Pass 2.
|
|
1041
|
+
if ((flags & FLAG_ACK) !== 0) {
|
|
1042
|
+
this.#process_ack(bytes, p, ack_end, now);
|
|
1043
|
+
this.#emit_notices();
|
|
1044
|
+
if (this.#disposed) return;
|
|
1045
|
+
}
|
|
1046
|
+
this.#process_frames(bytes, ack_end, length);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/**
|
|
1050
|
+
* RFC 9000 Appendix A.3.
|
|
1051
|
+
*/
|
|
1052
|
+
#expand_packet_number(truncated, bits) {
|
|
1053
|
+
const expected = this.#largest_rx + 1;
|
|
1054
|
+
const win = 2 ** bits;
|
|
1055
|
+
const hwin = win / 2;
|
|
1056
|
+
let candidate = expected - (expected % win) + truncated;
|
|
1057
|
+
if (candidate <= expected - hwin) {
|
|
1058
|
+
candidate += win;
|
|
1059
|
+
} else if (candidate > expected + hwin && candidate >= win) {
|
|
1060
|
+
candidate -= win;
|
|
1061
|
+
}
|
|
1062
|
+
return candidate;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
#drop(reason) {
|
|
1066
|
+
this.#stats.packets_dropped++;
|
|
1067
|
+
this.onMalformedDatagram.send1(reason);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
/**
|
|
1071
|
+
* Check a packet's structure without acting on it.
|
|
1072
|
+
* @returns {number} where the frames start, or -1 when it is malformed (already reported)
|
|
1073
|
+
*/
|
|
1074
|
+
#validate(bytes, start, end, flags) {
|
|
1075
|
+
const cursor = this.#cursor;
|
|
1076
|
+
cursor.position = start;
|
|
1077
|
+
let frames_start = start;
|
|
1078
|
+
|
|
1079
|
+
if ((flags & FLAG_ACK) !== 0) {
|
|
1080
|
+
const largest = varint_read(bytes, cursor, end);
|
|
1081
|
+
const delay = varint_read(bytes, cursor, end);
|
|
1082
|
+
const more = varint_read(bytes, cursor, end);
|
|
1083
|
+
const first = varint_read(bytes, cursor, end);
|
|
1084
|
+
if (largest < 0 || delay < 0 || more < 0 || first < 0) {
|
|
1085
|
+
this.#drop('truncated ACK');
|
|
1086
|
+
return -1;
|
|
1087
|
+
}
|
|
1088
|
+
if (first > largest || more + 1 > MAX_ACK_RANGES) {
|
|
1089
|
+
this.#drop('ACK out of range');
|
|
1090
|
+
return -1;
|
|
1091
|
+
}
|
|
1092
|
+
if (largest >= this.#next_pn) {
|
|
1093
|
+
// Not a malformed datagram to shrug off: the peer took in one that was not ours,
|
|
1094
|
+
// and will report it in every ACK it writes (see onProtocolError).
|
|
1095
|
+
this.#stats.packets_dropped++;
|
|
1096
|
+
this.onProtocolError.send1(`ACK of packet ${largest}, which was never sent (${this.#next_pn} sent): the peer took in a datagram that was not this side's`);
|
|
1097
|
+
return -1;
|
|
1098
|
+
}
|
|
1099
|
+
let low = largest - first;
|
|
1100
|
+
for (let i = 0; i < more; i++) {
|
|
1101
|
+
const gap = varint_read(bytes, cursor, end);
|
|
1102
|
+
const run = varint_read(bytes, cursor, end);
|
|
1103
|
+
if (gap < 0 || run < 0) {
|
|
1104
|
+
this.#drop('truncated ACK range');
|
|
1105
|
+
return -1;
|
|
1106
|
+
}
|
|
1107
|
+
const high = low - gap - 2;
|
|
1108
|
+
if (high < 0 || run > high) {
|
|
1109
|
+
this.#drop('ACK range below zero');
|
|
1110
|
+
return -1;
|
|
1111
|
+
}
|
|
1112
|
+
low = high - run;
|
|
1113
|
+
}
|
|
1114
|
+
frames_start = cursor.position;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
while (cursor.position < end) {
|
|
1118
|
+
const type = bytes[cursor.position++];
|
|
1119
|
+
if (type === FRAME_MESSAGE) {
|
|
1120
|
+
const length = varint_read(bytes, cursor, end);
|
|
1121
|
+
if (length < 0 || cursor.position + length > end) {
|
|
1122
|
+
this.#drop('truncated MESSAGE');
|
|
1123
|
+
return -1;
|
|
1124
|
+
}
|
|
1125
|
+
cursor.position += length;
|
|
1126
|
+
} else if (type === FRAME_PING) {
|
|
1127
|
+
// nothing
|
|
1128
|
+
} else if ((type & ~FRAME_STREAM_LANE_MASK) === FRAME_STREAM) {
|
|
1129
|
+
const lane = type & FRAME_STREAM_LANE_MASK;
|
|
1130
|
+
const offset = varint_read(bytes, cursor, end);
|
|
1131
|
+
const length = varint_read(bytes, cursor, end);
|
|
1132
|
+
if (lane >= LANE_COUNT || offset < 0 || length < 0 || cursor.position + length > end) {
|
|
1133
|
+
this.#drop('malformed STREAM');
|
|
1134
|
+
return -1;
|
|
1135
|
+
}
|
|
1136
|
+
cursor.position += length;
|
|
1137
|
+
} else {
|
|
1138
|
+
this.#drop(`unknown frame type ${type}`);
|
|
1139
|
+
return -1;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
return frames_start;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
#process_ack(bytes, start, end, now) {
|
|
1146
|
+
const cursor = this.#cursor;
|
|
1147
|
+
cursor.position = start;
|
|
1148
|
+
const largest = varint_read(bytes, cursor, end);
|
|
1149
|
+
const delay = varint_read(bytes, cursor, end);
|
|
1150
|
+
const more = varint_read(bytes, cursor, end);
|
|
1151
|
+
const first = varint_read(bytes, cursor, end);
|
|
1152
|
+
|
|
1153
|
+
const ranges = this.#ack_scratch;
|
|
1154
|
+
let count = 0;
|
|
1155
|
+
let high = largest;
|
|
1156
|
+
let low = largest - first;
|
|
1157
|
+
ranges[count++] = high;
|
|
1158
|
+
ranges[count++] = low;
|
|
1159
|
+
for (let i = 0; i < more; i++) {
|
|
1160
|
+
const gap = varint_read(bytes, cursor, end);
|
|
1161
|
+
const run = varint_read(bytes, cursor, end);
|
|
1162
|
+
high = low - gap - 2;
|
|
1163
|
+
low = high - run;
|
|
1164
|
+
ranges[count++] = high;
|
|
1165
|
+
ranges[count++] = low;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
const mask = this.#pkt_capacity - 1;
|
|
1169
|
+
|
|
1170
|
+
// RTT from the largest acknowledged, when it is newly acknowledged
|
|
1171
|
+
const largest_slot = largest & mask;
|
|
1172
|
+
let newly_acked_any = false;
|
|
1173
|
+
if (this.#pkt_pn[largest_slot] === largest) {
|
|
1174
|
+
this.#update_rtt(now - this.#pkt_sent_time[largest_slot], delay / ACK_DELAY_UNITS_PER_MS);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
for (let i = 0; i < count; i += 2) {
|
|
1178
|
+
const range_high = Math.min(ranges[i], this.#next_pn - 1);
|
|
1179
|
+
const range_low = Math.max(ranges[i + 1], this.#oldest_unretired);
|
|
1180
|
+
for (let pn = range_low; pn <= range_high; pn++) {
|
|
1181
|
+
if (this.#pkt_pn[pn & mask] !== pn) continue;
|
|
1182
|
+
newly_acked_any = true;
|
|
1183
|
+
this.#retire_acked(pn);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
if (largest > this.#largest_acked) this.#largest_acked = largest;
|
|
1188
|
+
if (newly_acked_any) this.#pto_count = 0;
|
|
1189
|
+
|
|
1190
|
+
this.#advance_oldest_unretired();
|
|
1191
|
+
this.#detect_lost(now);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
#process_frames(bytes, start, end) {
|
|
1195
|
+
const cursor = this.#cursor;
|
|
1196
|
+
cursor.position = start;
|
|
1197
|
+
let ack_eliciting = false;
|
|
1198
|
+
while (cursor.position < end) {
|
|
1199
|
+
const type = bytes[cursor.position++];
|
|
1200
|
+
if (type === FRAME_MESSAGE) {
|
|
1201
|
+
ack_eliciting = true;
|
|
1202
|
+
const length = varint_read(bytes, cursor, end);
|
|
1203
|
+
const at = cursor.position;
|
|
1204
|
+
cursor.position = at + length;
|
|
1205
|
+
const resume = cursor.position;
|
|
1206
|
+
this.onMessage.send3(bytes, at, length);
|
|
1207
|
+
if (this.#disposed) return;
|
|
1208
|
+
cursor.position = resume;
|
|
1209
|
+
} else if (type === FRAME_PING) {
|
|
1210
|
+
ack_eliciting = true;
|
|
1211
|
+
} else {
|
|
1212
|
+
ack_eliciting = true;
|
|
1213
|
+
const lane = type & FRAME_STREAM_LANE_MASK;
|
|
1214
|
+
const offset = varint_read(bytes, cursor, end);
|
|
1215
|
+
const length = varint_read(bytes, cursor, end);
|
|
1216
|
+
const at = cursor.position;
|
|
1217
|
+
cursor.position = at + length;
|
|
1218
|
+
const resume = cursor.position;
|
|
1219
|
+
const rx = this.#rx[lane];
|
|
1220
|
+
if (rx.failed) continue;
|
|
1221
|
+
if (!rx.receive(offset, bytes, at, length)) {
|
|
1222
|
+
this.onProtocolError.send1(`lane ${lane}: ${rx.failure}`);
|
|
1223
|
+
if (this.#disposed) return;
|
|
1224
|
+
cursor.position = resume;
|
|
1225
|
+
continue;
|
|
1226
|
+
}
|
|
1227
|
+
this.#deliver_lane(lane);
|
|
1228
|
+
if (this.#disposed) return;
|
|
1229
|
+
cursor.position = resume;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
if (ack_eliciting) this.#ack_pending = true;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
#deliver_lane(lane) {
|
|
1236
|
+
const rx = this.#rx[lane];
|
|
1237
|
+
const out = this.#message_out;
|
|
1238
|
+
for (; ;) {
|
|
1239
|
+
const length = rx.next_message(out);
|
|
1240
|
+
if (length === RX_NONE) return;
|
|
1241
|
+
if (length === RX_ERROR) {
|
|
1242
|
+
this.onProtocolError.send1(`lane ${lane}: ${rx.failure}`);
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
this.onMessage.send3(rx.bytes, out[0], length);
|
|
1246
|
+
if (this.#disposed) return;
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
#grow_unreliable_queue() {
|
|
1251
|
+
const capacity = this.#uq_offset.length * 2;
|
|
1252
|
+
const offset = new Int32Array(capacity);
|
|
1253
|
+
const length = new Int32Array(capacity);
|
|
1254
|
+
const token = new Int32Array(capacity);
|
|
1255
|
+
offset.set(this.#uq_offset);
|
|
1256
|
+
length.set(this.#uq_length);
|
|
1257
|
+
token.set(this.#uq_token);
|
|
1258
|
+
this.#uq_offset = offset;
|
|
1259
|
+
this.#uq_length = length;
|
|
1260
|
+
this.#uq_token = token;
|
|
1261
|
+
}
|
|
1262
|
+
}
|