@woosh/meep-engine 3.16.0 → 3.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -72
- package/editor/particles/effect/ParticleEffectDocument.d.ts +21 -6
- package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
- package/editor/particles/effect/ParticleEffectDocument.js +38 -17
- package/editor/view/node-graph/NodeGraphClipboard.d.ts +186 -0
- package/editor/view/node-graph/NodeGraphClipboard.d.ts.map +1 -0
- package/editor/view/node-graph/NodeGraphClipboard.js +231 -0
- package/editor/view/node-graph/NodeGraphEditorView.d.ts +59 -1
- package/editor/view/node-graph/NodeGraphEditorView.d.ts.map +1 -1
- package/editor/view/node-graph/NodeGraphEditorView.js +248 -5
- package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
- package/editor/view/node-graph/NodeGraphView.js +84 -8
- package/editor/view/node-graph/actions/connection_bind_actions.d.ts +23 -0
- package/editor/view/node-graph/actions/connection_bind_actions.d.ts.map +1 -0
- package/editor/view/node-graph/actions/connection_bind_actions.js +39 -0
- package/editor/view/particles/effect/ParticleCodeEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleCodeEditorView.js +4 -3
- package/editor/view/particles/effect/ParticleCurveEditorView.d.ts +20 -0
- package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -0
- package/editor/view/particles/effect/ParticleCurveEditorView.js +574 -0
- package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleEmitterInspectorView.js +27 -1
- package/editor/view/particles/effect/ParticleGradientEditorView.d.ts +24 -0
- package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -0
- package/editor/view/particles/effect/ParticleGradientEditorView.js +472 -0
- package/editor/view/particles/effect/ParticleGraphEditorView.d.ts +5 -0
- package/editor/view/particles/effect/ParticleGraphEditorView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleGraphEditorView.js +61 -31
- package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
- package/editor/view/particles/effect/ParticleNodeParametersView.js +33 -0
- package/editor/view/particles/effect/particle-editor.css +123 -35
- package/package.json +1 -1
- package/src/core/binary/allocator/OffsetAllocator.d.ts +25 -16
- package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
- package/src/core/binary/allocator/OffsetAllocator.js +10 -1
- package/src/core/collection/array/typed/float32_array_hash.d.ts +21 -0
- package/src/core/collection/array/typed/float32_array_hash.d.ts.map +1 -0
- package/src/core/collection/array/typed/float32_array_hash.js +38 -0
- package/src/core/graph/csr/CSRGraph.d.ts +8 -1
- package/src/core/graph/csr/CSRGraph.d.ts.map +1 -1
- package/src/core/graph/csr/CSRGraph.js +14 -6
- package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts +24 -0
- package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/LayoutProblem.js +27 -0
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +26 -0
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +28 -0
- package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts +92 -3
- package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/RouteGrid.js +405 -242
- package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts +50 -5
- package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/RouteSearch.js +160 -24
- package/src/core/model/node-graph/visual/layout/RouteSet.d.ts +7 -0
- package/src/core/model/node-graph/visual/layout/RouteSet.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/RouteSet.js +8 -0
- package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +9 -3
- package/src/core/model/node-graph/visual/layout/layout_build_problem.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_build_problem.js +7 -0
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts +9 -3
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_insert_lanes.js +17 -3
- package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts +9 -6
- package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_node_graph.js +49 -7
- package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts +11 -1
- package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/layout_order_layers.js +135 -16
- package/src/core/model/node-graph/visual/layout/route_connections.d.ts +29 -0
- package/src/core/model/node-graph/visual/layout/route_connections.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/route_connections.js +716 -309
- package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts +3 -2
- package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/route_grid_build.js +7 -15
- package/src/core/model/node-graph/visual/layout/route_nudge.d.ts +6 -0
- package/src/core/model/node-graph/visual/layout/route_nudge.d.ts.map +1 -1
- package/src/core/model/node-graph/visual/layout/route_nudge.js +42 -13
- package/src/engine/animation/AnimationUtils.js +246 -246
- package/src/engine/animation/Animations.js +74 -74
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2078 -2078
- package/src/engine/ecs/EventType.d.ts +0 -1
- package/src/engine/ecs/EventType.js +1 -26
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +1 -1
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +1 -1
- package/src/engine/ecs/ik/ik_write_local_rotation.js +3 -7
- package/src/engine/ecs/parent/EntityNode.d.ts.map +1 -1
- package/src/engine/ecs/parent/EntityNode.js +4 -9
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +360 -364
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts +41 -0
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts.map +1 -0
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.js +40 -0
- package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +8 -0
- package/src/engine/ecs/transform/t64_announce_change.d.ts +10 -7
- package/src/engine/ecs/transform/t64_announce_change.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_announce_change.js +12 -12
- package/src/engine/ecs/transform/t64_set_rotation_axis_angle.d.ts +25 -0
- package/src/engine/ecs/transform/t64_set_rotation_axis_angle.d.ts.map +1 -0
- package/src/engine/ecs/transform/t64_set_rotation_axis_angle.js +45 -0
- package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts +30 -0
- package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts.map +1 -0
- package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js +29 -0
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +13 -21
- package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
- package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +4 -8
- package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
- package/src/engine/graphics3/LightSystem.js +4 -8
- package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
- package/src/engine/graphics3/MeshSystem.js +9 -19
- package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/ParticleEmitterSystem.js +4 -8
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics3/ShadedGeometrySystem.js +4 -10
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts +1 -1
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts.map +1 -1
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +4 -8
- package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.js +218 -218
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +2 -5
- package/src/engine/sound/ecs/SoundListenerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/SoundListenerSystem.js +6 -8
- package/src/engine/sound/simulation/AcousticSimulator.d.ts +11 -8
- package/src/engine/sound/simulation/AcousticSimulator.d.ts.map +1 -1
- package/src/engine/sound/simulation/AcousticSimulator.js +45 -36
- package/src/engine/sound/simulation/README.md +2 -2
- package/src/engine/sound/simulation/core/OcclusionSolver.d.ts.map +1 -1
- package/src/engine/sound/simulation/core/VolumeField.d.ts +9 -9
- package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
- package/src/engine/sound/simulation/core/VolumeField.js +29 -13
- package/src/engine/sound/simulation/core/acoustic_occlusion_solve.d.ts +31 -0
- package/src/engine/sound/simulation/core/acoustic_occlusion_solve.d.ts.map +1 -0
- package/src/engine/sound/simulation/core/acoustic_occlusion_solve.js +134 -0
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts +0 -4
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts.map +1 -1
- package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +5 -11
- package/src/shade/playground/particle_editor/README.md +43 -2
- package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
- package/src/shade/playground/particle_system/particle_prototype.js +4 -5
- package/src/shade/playground/particle_system/particle_scene.js +4 -4
- package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
- package/src/shade/playground/volumetrics_froxel/main.js +6 -1
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +13 -1
- package/src/shade/renderer/particles/DESIGN.md +104 -19
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts +64 -50
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
- package/src/shade/renderer/particles/GPUParticleSystem.js +176 -78
- package/src/shade/renderer/particles/ParticleConstants.d.ts +59 -23
- package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
- package/src/shade/renderer/particles/ParticleConstants.js +66 -23
- package/src/shade/renderer/particles/ParticleRenderMode.d.ts +19 -0
- package/src/shade/renderer/particles/ParticleRenderMode.d.ts.map +1 -0
- package/src/shade/renderer/particles/ParticleRenderMode.js +33 -0
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +167 -166
- package/src/shade/renderer/particles/data/particle_emitter_record.d.ts +37 -0
- package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -0
- package/src/shade/renderer/particles/data/particle_emitter_record.js +109 -0
- package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +3 -3
- package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +303 -303
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +18 -0
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +152 -133
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +0 -11
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +720 -621
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.js +8 -3
- package/src/shade/renderer/particles/graph/flatten_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/flatten_particle_graph.js +244 -213
- 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 +6 -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 +294 -319
- package/src/shade/renderer/particles/graph/groups/particle_groups_noise.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_groups_noise.js +524 -517
- package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts +22 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.js +517 -0
- package/src/shade/renderer/particles/graph/groups/simplex_reference.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/simplex_reference.js +185 -159
- package/src/shade/renderer/particles/graph/make_particle_group.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/make_particle_group.js +2 -20
- package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts +17 -0
- package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/particle_compare_ops.js +22 -0
- package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts +28 -8
- package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_graph_diagnostic.js +49 -25
- package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +40 -0
- package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_node_parameters.js +312 -234
- package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/particle_node_presentation.js +59 -3
- package/src/shade/renderer/particles/graph/particle_ramp.d.ts +230 -0
- package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/particle_ramp.js +403 -0
- package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts +7 -1
- package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/validate_particle_graph.js +66 -10
- package/src/shade/renderer/particles/graph_particles.d.ts +23 -69
- package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles.js +105 -262
- package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles_avboit.js +3 -2
- package/src/shade/renderer/particles/graph_particles_billboard.d.ts +37 -0
- package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph_particles_billboard.js +93 -0
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts +51 -22
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/InstructionStream.js +98 -38
- package/src/shade/renderer/particles/isa/ParticleProgram.d.ts +49 -8
- package/src/shade/renderer/particles/isa/ParticleProgram.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleProgram.js +95 -150
- package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +306 -64
- package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleVMISA.js +505 -136
- package/src/shade/renderer/particles/isa/particle_assembly.d.ts +36 -12
- package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/particle_assembly.js +354 -139
- package/src/shade/renderer/particles/isa/validate_particle_program.d.ts +9 -0
- package/src/shade/renderer/particles/isa/validate_particle_program.d.ts.map +1 -0
- package/src/shade/renderer/particles/isa/validate_particle_program.js +128 -0
- package/src/shade/renderer/particles/layout/ParticleLayout.d.ts +23 -0
- package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
- package/src/shade/renderer/particles/layout/ParticleLayout.js +68 -0
- package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts +77 -0
- package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.js +219 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts +83 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +283 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +133 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +334 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts +117 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.js +70 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts +97 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +462 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts +116 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js +687 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts +57 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +860 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts +115 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.js +264 -0
- package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +81 -42
- package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/optimize_particle_program.js +477 -478
- package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts +100 -0
- package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/particle_integer_bounds.js +236 -0
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts +139 -59
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +764 -647
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts +40 -7
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +376 -213
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts +30 -3
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +337 -223
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +24 -38
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +166 -206
- package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts +99 -0
- package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/pass_allocate_registers.js +313 -0
- package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts +3 -2
- package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_dedup_constants.js +198 -197
- package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts +19 -0
- package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +678 -561
- package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts +22 -0
- package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/pass_inline_constants.js +221 -0
- package/src/shade/renderer/particles/optimizer/pass_narrow_widths.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_narrow_widths.js +63 -72
- package/src/shade/renderer/particles/optimizer/pass_pack_registers.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_pack_registers.js +87 -86
- package/src/shade/renderer/particles/optimizer/pass_peephole.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_peephole.js +392 -271
- package/src/shade/renderer/particles/optimizer/pass_propagate_copies.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_propagate_copies.js +361 -268
- package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts +4 -0
- package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts.map +1 -0
- package/src/shade/renderer/particles/optimizer/pass_schedule.js +244 -0
- package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.js +154 -151
- package/src/shade/renderer/particles/particle_test_fixtures.d.ts +20 -0
- package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +1 -1
- package/src/shade/renderer/particles/particle_test_fixtures.js +229 -203
- package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +99 -25
- package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/EmitterRegistry.js +438 -286
- package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +109 -0
- package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -0
- package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +127 -0
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +87 -102
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/ParticleEmitter.js +184 -163
- package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts +130 -0
- package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts.map +1 -0
- package/src/shade/renderer/particles/runtime/ProgramHeap.js +595 -0
- package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts +91 -0
- package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts.map +1 -0
- package/src/shade/renderer/particles/runtime/ProgramPlacement.js +106 -0
- package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +5 -2
- package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/create_particle_effect.js +22 -19
- package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts +28 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.js +136 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts +35 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.js +133 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts +18 -9
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +20 -80
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts +33 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +114 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts +8 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +33 -101
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts +45 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -0
- package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +123 -0
- package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +51 -0
- package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +1 -0
- package/src/shade/renderer/particles/sort/graph_particle_sort.js +120 -0
- package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts +6 -0
- package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.js +16 -0
- package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +4 -1
- package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
- package/src/shade/renderer/particles/vm/ParticleVMReference.js +261 -140
- package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
- package/src/shade/renderer/particles/vm/chunk_particle_vm.js +217 -255
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts +43 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts.map +1 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.js +55 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts +62 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts.map +1 -0
- package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.js +86 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.js +32 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts +9 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.js +19 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/README.md +65 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts +24 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.js +83 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts +25 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.js +42 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts +31 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.js +80 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts +26 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.js +109 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts +38 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.js +129 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts +21 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.js +35 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts +19 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.js +28 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts +13 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.js +22 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.js +59 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts +23 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.js +74 -0
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +7 -0
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +7 -0
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts +34 -1
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +41 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +3 -2
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +49 -10
- package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
- package/src/view/minimap/dom/MinimapCameraView.js +4 -9
- package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts +0 -15
- package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts +0 -45
- package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts +0 -24
- package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts.map +0 -1
- package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts +0 -19
- package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts.map +0 -1
- package/src/engine/ecs/transform/__probe.d.ts +0 -4
- package/src/engine/ecs/transform/__probe.d.ts.map +0 -1
- package/src/engine/ecs/util/hideEntityGracefully.d.ts +0 -9
- package/src/engine/ecs/util/hideEntityGracefully.d.ts.map +0 -1
- package/src/engine/sound/simulation/core/OcclusionSolver.js +0 -112
- package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts +0 -27
- package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts.map +0 -1
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts +0 -14
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +0 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts +0 -156
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/Emitter.d.ts +0 -219
- package/src/shade/renderer/particles/runtime/Emitter.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts +0 -77
- package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/ProgramArena.d.ts +0 -89
- package/src/shade/renderer/particles/runtime/ProgramArena.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/ProgramArena.js +0 -155
- package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts +0 -15
- package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts.map +0 -1
- package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts +0 -34
- package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts.map +0 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts +0 -32
- package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts.map +0 -1
|
@@ -1,213 +1,376 @@
|
|
|
1
|
-
import { PARTICLE_RECORD_WORD_COUNT } from "../ParticleConstants.js";
|
|
2
|
-
import { VM_BUILTIN } from "../isa/ParticleVMISA.js";
|
|
3
|
-
import { execute_particle_vm } from "../vm/ParticleVMReference.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* - `tolerance`, for `peephole.fuse_multiply_add` (off by default), which is a rounding difference
|
|
26
|
-
* and so has no shape to name.
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* @param {
|
|
115
|
-
* @param {
|
|
116
|
-
* @param {number}
|
|
117
|
-
* @param {
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
1
|
+
import { PARTICLE_RECORD_WORD_COUNT, PARTICLE_VM_INSTRUCTION_WORDS, PARTICLE_VM_REGISTER_SLOTS } from "../ParticleConstants.js";
|
|
2
|
+
import { VM_BUILTIN, VM_KIND, VM_MAX_WIDTH, VM_OP } from "../isa/ParticleVMISA.js";
|
|
3
|
+
import { execute_particle_vm } from "../vm/ParticleVMReference.js";
|
|
4
|
+
import { decode_particle_instructions, particle_read_slots } from "./particle_program_analysis.js";
|
|
5
|
+
import { PARTICLE_ZERO_ABSORBING_OPS } from "./pass_fold_constants.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The property every optimizer pass is held to: an optimized program leaves the same record, the
|
|
9
|
+
* same kill flag and the same RNG state as the one it was built from — to the bit.
|
|
10
|
+
*
|
|
11
|
+
* This is a differential harness rather than a set of expected outputs because the interesting
|
|
12
|
+
* failures are not "the optimizer produced something odd", they are "the optimizer produced
|
|
13
|
+
* something plausible that computes a slightly different number". Running both programs on
|
|
14
|
+
* {@link execute_particle_vm} and comparing the whole observable state catches those without anyone
|
|
15
|
+
* having to predict them.
|
|
16
|
+
*
|
|
17
|
+
* ## Bit-identical, and the two relaxations that are named rather than tolerated
|
|
18
|
+
*
|
|
19
|
+
* Float rewrites that look obviously fine mostly are not, so the default here is that the bits
|
|
20
|
+
* match. Two rewrites deliberately do not, and each has a comparison mode that accepts EXACTLY what
|
|
21
|
+
* it gives up and nothing else — a blanket tolerance would accept those and also whatever else went
|
|
22
|
+
* wrong:
|
|
23
|
+
*
|
|
24
|
+
* - `reached_by_zero_fold`, for `fold_constants.fold_multiply_by_zero` (on by default).
|
|
25
|
+
* - `tolerance`, for `peephole.fuse_multiply_add` (off by default), which is a rounding difference
|
|
26
|
+
* and so has no shape to name.
|
|
27
|
+
*
|
|
28
|
+
* The third relaxation, `fold_constants.fold_inexact`, needs nothing here, and that absence is the
|
|
29
|
+
* point of it: the fold evaluates each operation the way the reference executes it, so a program
|
|
30
|
+
* with the transcendentals folded is bit-identical HERE and differs only against a GPU. Which is
|
|
31
|
+
* why this harness cannot vouch for that one — `../vm/chunk_particle_vm.spec.js` is where the two
|
|
32
|
+
* executors meet, and its 1e-4 tolerance is exactly the slack the option spends.
|
|
33
|
+
*
|
|
34
|
+
* ## Why the zero fold is a reachability question and not a shape one
|
|
35
|
+
*
|
|
36
|
+
* This mode used to be called `absorbed_zero` and accepted two record shapes: a `-0` that had become
|
|
37
|
+
* a `+0`, and a `NaN` that had become a zero. Those are what folding `x * 0` to `+0` gives up AT THE
|
|
38
|
+
* MULTIPLY — and the record is not the multiply. The substitution lands in a register, and the next
|
|
39
|
+
* instruction to read that register is free to turn it into anything:
|
|
40
|
+
*
|
|
41
|
+
* LOG r1, r0 ; r0 is zero, so r1 is -Inf
|
|
42
|
+
* SCALE r3, r2, r1 ; r2 is -0. -0 * -Inf is NaN; folded, r3 is +0
|
|
43
|
+
* CMP_GE r4, r3, r2 ; NaN >= -0 is false. +0 >= -0 is true. The record word is 0, then 1.
|
|
44
|
+
*
|
|
45
|
+
* A `0` that became a `1` is neither of the two shapes, and no per-word test on the record can name
|
|
46
|
+
* it — a division by the substituted zero turns the same `NaN` into an `Infinity` instead, and one
|
|
47
|
+
* more comparison launders that back into a finite number. Both of those came out of the fuzzer
|
|
48
|
+
* (`random_particle_program` seeds 148 and 2743), past the range the specs were sweeping.
|
|
49
|
+
*
|
|
50
|
+
* So what is bounded is not the VALUE but the REACH. {@link particle_multiply_reach} marks every
|
|
51
|
+
* record word a `MUL` or `SCALE` result can flow into, statically and without caring which multiply
|
|
52
|
+
* had a zero operand; the mode stops comparing those words and holds every other one to the bit.
|
|
53
|
+
* Over the fuzz corpus that leaves about 94% of the stored words still compared exactly, which is
|
|
54
|
+
* the part of the promise that survived — a pass that moved a value the fold never touched is still
|
|
55
|
+
* caught, and only the words genuinely downstream of a multiply are given up.
|
|
56
|
+
*
|
|
57
|
+
* ## Environments
|
|
58
|
+
*
|
|
59
|
+
* A program reads more than its constants — record words, builtins, the RNG, curve samples — and a
|
|
60
|
+
* pass that mishandled any of those could still agree on a single run. {@link PARTICLE_ENVIRONMENTS}
|
|
61
|
+
* varies all of them, including a record pre-filled with values a `LOAD_ATTR` can pick up.
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/** Distinct, non-round values, so a builtin read from the wrong id or lane lands on a wrong number. */
|
|
65
|
+
const BUILTINS_A = [];
|
|
66
|
+
BUILTINS_A[VM_BUILTIN.DELTA_TIME] = [0.0125, 0, 0, 0];
|
|
67
|
+
BUILTINS_A[VM_BUILTIN.EMITTER_AGE] = [3.5, 0, 0, 0];
|
|
68
|
+
BUILTINS_A[VM_BUILTIN.EMITTER_POSITION] = [1.25, -2.5, 7, 1];
|
|
69
|
+
BUILTINS_A[VM_BUILTIN.EMITTER_DIRECTION] = [0.6, -0.5, -0.8, 0];
|
|
70
|
+
BUILTINS_A[VM_BUILTIN.EMITTER_UP] = [-0.25, 1, 0.375, 0];
|
|
71
|
+
BUILTINS_A[VM_BUILTIN.PARTICLE_INDEX] = [11, 0, 0, 0];
|
|
72
|
+
BUILTINS_A[VM_BUILTIN.SPAWN_FRACTION] = [0.75, 0, 0, 0];
|
|
73
|
+
BUILTINS_A[VM_BUILTIN.TIME] = [12.5, 0, 0, 0];
|
|
74
|
+
|
|
75
|
+
/** A second set, negated and shuffled, so nothing passes by holding a builtin's value constant. */
|
|
76
|
+
const BUILTINS_B = BUILTINS_A.map(v => v.map(x => -x + 0.5));
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* A record with something in every user word — a program that loads an attribute the harness left
|
|
80
|
+
* at zero is a program whose loads are all interchangeable.
|
|
81
|
+
*
|
|
82
|
+
* @returns {Uint32Array}
|
|
83
|
+
*/
|
|
84
|
+
function seeded_record() {
|
|
85
|
+
const record = new Uint32Array(PARTICLE_RECORD_WORD_COUNT);
|
|
86
|
+
const floats = new Float32Array(record.buffer);
|
|
87
|
+
|
|
88
|
+
for (let i = 1; i < PARTICLE_RECORD_WORD_COUNT; i++) {
|
|
89
|
+
floats[i] = (i % 7) - 3.25 + i / 32;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return record;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** @param {number} handle @param {number} t @returns {number} */
|
|
96
|
+
const sample_curve = (handle, t) => Math.sin(handle + t * 3) * 0.5 + handle * 0.125;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The contexts a program is compared in. Seeds differ so a pass that dropped or added a draw shows
|
|
100
|
+
* up as a diverging RNG state rather than only as a diverging record.
|
|
101
|
+
*
|
|
102
|
+
* @type {Array<{name: string, builtins: number[][], rng_state: number, record: () => Uint32Array}>}
|
|
103
|
+
*/
|
|
104
|
+
export const PARTICLE_ENVIRONMENTS = [
|
|
105
|
+
{ name: "zeroed record, seed 1", builtins: BUILTINS_A, rng_state: 1, record: () => new Uint32Array(PARTICLE_RECORD_WORD_COUNT) },
|
|
106
|
+
{ name: "seeded record, seed 1", builtins: BUILTINS_A, rng_state: 1, record: seeded_record },
|
|
107
|
+
{ name: "seeded record, seed 0x9e3779b9", builtins: BUILTINS_B, rng_state: 0x9e3779b9, record: seeded_record },
|
|
108
|
+
{ name: "seeded record, seed 12345", builtins: BUILTINS_B, rng_state: 12345, record: seeded_record },
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Run one section and return everything a program can be observed to have done.
|
|
113
|
+
*
|
|
114
|
+
* @param {object} params
|
|
115
|
+
* @param {Uint32Array} params.words
|
|
116
|
+
* @param {Float32Array|number[]} params.constants
|
|
117
|
+
* @param {number} params.register_count
|
|
118
|
+
* @param {object} params.environment one of {@link PARTICLE_ENVIRONMENTS}
|
|
119
|
+
* @returns {{ record: Uint32Array, killed: boolean, rng_state: number }}
|
|
120
|
+
*/
|
|
121
|
+
export function run_particle_section({ words, constants, register_count, environment }) {
|
|
122
|
+
const record = environment.record();
|
|
123
|
+
|
|
124
|
+
const result = execute_particle_vm({
|
|
125
|
+
words,
|
|
126
|
+
constants: constants instanceof Float32Array ? constants : new Float32Array(constants),
|
|
127
|
+
register_count,
|
|
128
|
+
record,
|
|
129
|
+
builtins: environment.builtins,
|
|
130
|
+
rng_state: environment.rng_state,
|
|
131
|
+
sampleCurve: sample_curve,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return { record, killed: result.killed, rng_state: result.rng_state };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Which record words — and whether the kill flag — the result of a zero-absorbing opcode can reach.
|
|
139
|
+
*
|
|
140
|
+
* This is the bound on `fold_constants.fold_multiply_by_zero`, and it is deliberately blunt in the
|
|
141
|
+
* one direction that keeps it sound: every instruction in
|
|
142
|
+
* {@link PARTICLE_ZERO_ABSORBING_OPS} is treated as though its result had been substituted, because
|
|
143
|
+
* which of them had a compile-time zero operand is a fact about the optimizer's analysis and not
|
|
144
|
+
* about the program. The set comes from the pass rather than being restated here, so an opcode added
|
|
145
|
+
* to the rewrite is an opcode this follows. Everything the marked slots flow into is marked too, and a
|
|
146
|
+
* store carries the mark into the record word it writes.
|
|
147
|
+
*
|
|
148
|
+
* A `LOAD_ATTR` of a marked record word marks its destination back, so a value that went out through
|
|
149
|
+
* the record and came back in is still followed. Slots are cleared by a write whose sources are all
|
|
150
|
+
* unmarked — the value there is then the same in both programs — while record words are only ever
|
|
151
|
+
* added to, because a store cannot un-write what an earlier one already made unequal.
|
|
152
|
+
*
|
|
153
|
+
* Static, so it over-approximates the runs: a lane that never actually held a substituted zero is
|
|
154
|
+
* marked anyway. That is the right direction to be wrong in, and it is not blunt in practice — see
|
|
155
|
+
* the 94% in the module comment.
|
|
156
|
+
*
|
|
157
|
+
* @param {Uint32Array} words a packed instruction section
|
|
158
|
+
* @returns {{record: Uint8Array, killed: boolean}}
|
|
159
|
+
*/
|
|
160
|
+
export function particle_multiply_reach(words) {
|
|
161
|
+
const decoded = decode_particle_instructions(instruction_tuples(words));
|
|
162
|
+
|
|
163
|
+
/** One flag per register slot, with room for an operand run that ends on the last of them. */
|
|
164
|
+
const slot = new Uint8Array(PARTICLE_VM_REGISTER_SLOTS + VM_MAX_WIDTH);
|
|
165
|
+
const record = new Uint8Array(PARTICLE_RECORD_WORD_COUNT);
|
|
166
|
+
|
|
167
|
+
let killed = false;
|
|
168
|
+
|
|
169
|
+
for (const instruction of decoded) {
|
|
170
|
+
// Nothing past a `HALT` runs, so nothing past it can carry anything anywhere.
|
|
171
|
+
if (instruction.op === VM_OP.HALT) {
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let reached = false;
|
|
176
|
+
|
|
177
|
+
for (const read of instruction.reads) {
|
|
178
|
+
for (const s of particle_read_slots(read)) {
|
|
179
|
+
reached = reached || slot[s] === 1;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// The record operands are read straight out of the words: `LOAD_ATTR` keeps its offset and
|
|
184
|
+
// component count in s0 and s1, `STORE_ATTR` in s1 and s2 behind the value it stores.
|
|
185
|
+
if (instruction.op === VM_OP.LOAD_ATTR) {
|
|
186
|
+
const offset = instruction.words[1];
|
|
187
|
+
const components = instruction.words[2];
|
|
188
|
+
|
|
189
|
+
for (let lane = 0; lane < components; lane++) {
|
|
190
|
+
reached = reached || record[offset + lane] === 1;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (instruction.op === VM_OP.STORE_ATTR) {
|
|
195
|
+
const offset = instruction.words[2];
|
|
196
|
+
const components = instruction.words[3];
|
|
197
|
+
const value = instruction.sources[0];
|
|
198
|
+
const stored = value.kind === VM_KIND.REG ? particle_read_slots(value, components) : [];
|
|
199
|
+
|
|
200
|
+
for (let lane = 0; lane < components; lane++) {
|
|
201
|
+
record[offset + lane] |= lane < stored.length ? slot[stored[lane]] : 0;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (instruction.op === VM_OP.KILL) {
|
|
208
|
+
killed = killed || reached;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (instruction.write === null) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const substitutes = PARTICLE_ZERO_ABSORBING_OPS.has(instruction.op);
|
|
217
|
+
|
|
218
|
+
for (let lane = 0; lane < instruction.write.span; lane++) {
|
|
219
|
+
slot[instruction.write.base + lane] = substitutes || reached ? 1 : 0;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return { record, killed };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* The reach of both sides at once. The two programs address different registers — packing moves
|
|
228
|
+
* them — so the sections are walked separately and only the record words are put together.
|
|
229
|
+
*
|
|
230
|
+
* @param {Uint32Array} before
|
|
231
|
+
* @param {Uint32Array} after
|
|
232
|
+
* @returns {{record: Uint8Array, killed: boolean}}
|
|
233
|
+
*/
|
|
234
|
+
function combined_multiply_reach(before, after) {
|
|
235
|
+
const a = particle_multiply_reach(before);
|
|
236
|
+
const b = particle_multiply_reach(after);
|
|
237
|
+
|
|
238
|
+
for (let i = 0; i < a.record.length; i++) {
|
|
239
|
+
a.record[i] |= b.record[i];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return { record: a.record, killed: a.killed || b.killed };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* A packed section as the four-word tuples {@link decode_particle_instructions} reads.
|
|
247
|
+
*
|
|
248
|
+
* @param {Uint32Array} words
|
|
249
|
+
* @returns {Uint32Array[]} views, so nothing is copied
|
|
250
|
+
*/
|
|
251
|
+
function instruction_tuples(words) {
|
|
252
|
+
const out = [];
|
|
253
|
+
|
|
254
|
+
for (let base = 0; base < words.length; base += PARTICLE_VM_INSTRUCTION_WORDS) {
|
|
255
|
+
out.push(words.subarray(base, base + PARTICLE_VM_INSTRUCTION_WORDS));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return out;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Compare two runs. Record words are compared as raw bits first — which is the strict answer,
|
|
263
|
+
* including the sign of a zero — and only a pair that differs is re-read as floats, so a `NaN` on
|
|
264
|
+
* both sides counts as agreement whatever payload it carries.
|
|
265
|
+
*
|
|
266
|
+
* @param {{record: Uint32Array, killed: boolean, rng_state: number}} before
|
|
267
|
+
* @param {{record: Uint32Array, killed: boolean, rng_state: number}} after
|
|
268
|
+
* @param {object} [comparison]
|
|
269
|
+
* @param {number} [comparison.tolerance] relative slack on record words; zero means the bits match
|
|
270
|
+
* @param {{record: Uint8Array, killed: boolean}|null} [comparison.reach] what the zero fold is
|
|
271
|
+
* allowed to have changed, from {@link particle_multiply_reach}. A marked word is not compared at
|
|
272
|
+
* all — there is no shape left to hold it to, which is the whole of the argument in the module
|
|
273
|
+
* comment — and every other one is held to the bit.
|
|
274
|
+
* @returns {string|null} what differs, or `null` when nothing does
|
|
275
|
+
*/
|
|
276
|
+
export function diff_particle_section_result(before, after, { tolerance = 0, reach = null } = {}) {
|
|
277
|
+
if (before.killed !== after.killed && !(reach !== null && reach.killed)) {
|
|
278
|
+
return `kill flag: ${before.killed} -> ${after.killed}`;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Never relaxed. `RANDOM` has side effects, so no pass may add, drop or reorder a draw, and a
|
|
282
|
+
// substituted zero cannot reach the stream either — there is nothing in this ISA that makes a
|
|
283
|
+
// draw conditional on a value.
|
|
284
|
+
if (before.rng_state !== after.rng_state) {
|
|
285
|
+
return `RNG state: ${before.rng_state} -> ${after.rng_state}`;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const a = new Float32Array(before.record.buffer);
|
|
289
|
+
const b = new Float32Array(after.record.buffer);
|
|
290
|
+
|
|
291
|
+
for (let i = 0; i < before.record.length; i++) {
|
|
292
|
+
if (before.record[i] === after.record[i]) {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (Number.isNaN(a[i]) && Number.isNaN(b[i])) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (reach !== null && reach.record[i] === 1) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (tolerance > 0 && Math.abs(a[i] - b[i]) <= tolerance * Math.max(1, Math.abs(a[i]), Math.abs(b[i]))) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return `record word ${i}: ${a[i]} (0x${before.record[i].toString(16)})`
|
|
309
|
+
+ ` -> ${b[i]} (0x${after.record[i].toString(16)})`;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Compare an optimized section against the original across every environment.
|
|
317
|
+
*
|
|
318
|
+
* The two may have different register counts and different constant pools — the optimizer shrinks
|
|
319
|
+
* one and may extend the other — so both are passed per side rather than assumed shared.
|
|
320
|
+
*
|
|
321
|
+
* @param {object} params
|
|
322
|
+
* @param {{words: Uint32Array, constants: Float32Array|number[], register_count: number}} params.before
|
|
323
|
+
* @param {{words: Uint32Array, constants: Float32Array|number[], register_count: number}} params.after
|
|
324
|
+
* @param {Array<object>} [params.environments]
|
|
325
|
+
* @param {object} [params.comparison] see {@link diff_particle_section_result}, plus
|
|
326
|
+
* `reached_by_zero_fold` — the reach is a property of the two SECTIONS rather than of a run, so it
|
|
327
|
+
* is worked out once here and handed down as `reach`
|
|
328
|
+
* @returns {string|null} a description of the first divergence, or `null`
|
|
329
|
+
*/
|
|
330
|
+
export function diff_particle_sections({ before, after, environments = PARTICLE_ENVIRONMENTS, comparison }) {
|
|
331
|
+
const { reached_by_zero_fold = false, ...rest } = comparison ?? {};
|
|
332
|
+
const resolved = reached_by_zero_fold
|
|
333
|
+
? { ...rest, reach: combined_multiply_reach(before.words, after.words) }
|
|
334
|
+
: rest;
|
|
335
|
+
|
|
336
|
+
for (const environment of environments) {
|
|
337
|
+
const difference = diff_particle_section_result(
|
|
338
|
+
run_particle_section({ ...before, environment }),
|
|
339
|
+
run_particle_section({ ...after, environment }),
|
|
340
|
+
resolved
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
if (difference !== null) {
|
|
344
|
+
return `${environment.name}: ${difference}`;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Compare every section of two compiled programs.
|
|
353
|
+
*
|
|
354
|
+
* @param {ParticleProgram} before
|
|
355
|
+
* @param {ParticleProgram} after
|
|
356
|
+
* @param {object} [comparison] see {@link diff_particle_sections}, plus `environments`
|
|
357
|
+
* @returns {string|null}
|
|
358
|
+
*/
|
|
359
|
+
export function diff_particle_programs(before, after, comparison = {}) {
|
|
360
|
+
const { environments = PARTICLE_ENVIRONMENTS, ...rest } = comparison;
|
|
361
|
+
|
|
362
|
+
for (const section of ["init", "update"]) {
|
|
363
|
+
const difference = diff_particle_sections({
|
|
364
|
+
before: { words: before[section], constants: before.constants, register_count: before.register_count },
|
|
365
|
+
after: { words: after[section], constants: after.constants, register_count: after.register_count },
|
|
366
|
+
environments,
|
|
367
|
+
comparison: rest,
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
if (difference !== null) {
|
|
371
|
+
return `${section}: ${difference}`;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return null;
|
|
376
|
+
}
|