@woosh/meep-engine 3.16.0 → 3.17.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/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-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/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/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/ProgramArena.d.ts +26 -0
- package/src/shade/renderer/particles/runtime/ProgramArena.d.ts.map +1 -1
- 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/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/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.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
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import { PARTICLE_RECORD_WORD_COUNT } from "../../ParticleConstants.js";
|
|
2
|
+
import {
|
|
3
|
+
VM_KIND,
|
|
4
|
+
VM_MAX_WIDTH,
|
|
5
|
+
VM_OP,
|
|
6
|
+
VM_SWIZZLE_IDENTITY,
|
|
7
|
+
pack_swizzle,
|
|
8
|
+
swizzle_selector,
|
|
9
|
+
vm_dest_width,
|
|
10
|
+
vm_f32_value,
|
|
11
|
+
vm_operand_base,
|
|
12
|
+
} from "../../isa/ParticleVMISA.js";
|
|
13
|
+
import { decode_particle_instruction } from "../particle_program_analysis.js";
|
|
14
|
+
import { vm_semantics_of } from "../particle_vm_semantics.js";
|
|
15
|
+
import { PV } from "./particle_vector_graph.js";
|
|
16
|
+
import { identity_lanes, identity_of } from "./particle_vector_rules.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Read one section of a compiled program into a {@link ./particle_vector_graph.js vector graph}.
|
|
20
|
+
*
|
|
21
|
+
* What a section MEANS is its final record, the kill flag it sets and the RNG state it ends on, and
|
|
22
|
+
* everything that draws out of that is done here: a load of a word that was stored is the stored
|
|
23
|
+
* value, a word put back as it was found is not stored, kills are a set, draws are a sequence that
|
|
24
|
+
* may be re-cut, and nothing past a `HALT` is read.
|
|
25
|
+
*
|
|
26
|
+
* What is different is the unit. The register file holds not values but PLACES IN values: slot `s`
|
|
27
|
+
* holds lane `l` of value `v`. Reading a run of slots then asks one question — do they all come from
|
|
28
|
+
* one value? If they do, the read is that value through a swizzle, which is what a source word is and
|
|
29
|
+
* costs nothing. If they do not, it is a `BUILD`, and the copies it costs are visible from here on
|
|
30
|
+
* rather than discovered at the end.
|
|
31
|
+
*
|
|
32
|
+
* That is the whole of the change, and it is why the frontend's vectors reach the other side: a
|
|
33
|
+
* `vec3` the compiler emitted as one instruction is read back as one value, not inferred from three.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {object} ParticleVectorPlace
|
|
38
|
+
* @property {number} value the class the slot's value belongs to
|
|
39
|
+
* @property {number} lane which lane of it the slot holds
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {object} ParticleLiftedVectorSection
|
|
44
|
+
* @property {Array<{word: number, place: ParticleVectorPlace, origin: number}>} stores record words
|
|
45
|
+
* whose final contents differ from what the section found, in word order
|
|
46
|
+
* @property {ParticleVectorPlace[]} kills distinct kill conditions, in the order they were met
|
|
47
|
+
* @property {number} draw_count draws taken off the RNG
|
|
48
|
+
* @property {number[]} draws per draw, the class of the `RANDOM` that takes it
|
|
49
|
+
* @property {number[]} draw_lanes per draw, which lane of that class it is
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {import("./particle_vector_graph.js").ParticleVectorGraph} graph
|
|
54
|
+
* @param {ArrayLike<ArrayLike<number>>} instructions four-word tuples, in program order
|
|
55
|
+
* @param {object} params
|
|
56
|
+
* @param {ArrayLike<number>} params.constants
|
|
57
|
+
* @param {number} params.register_slots
|
|
58
|
+
* @returns {ParticleLiftedVectorSection|null} `null` when the section reaches outside that file, or
|
|
59
|
+
* uses an opcode this lift has no model for
|
|
60
|
+
*/
|
|
61
|
+
export function lift_particle_vector_section(graph, instructions, { constants, register_slots }) {
|
|
62
|
+
const zero = { value: graph.constant(0), lane: 0 };
|
|
63
|
+
/** @type {ParticleVectorPlace[]} what each slot holds; both executors start a particle with a zeroed file */
|
|
64
|
+
const reg = new Array(register_slots).fill(zero);
|
|
65
|
+
/** @type {Map<number, ParticleVectorPlace>} per record word, what it held when the section began */
|
|
66
|
+
const initial = new Map();
|
|
67
|
+
/** @type {Map<number, ParticleVectorPlace>} per record word, what it holds now */
|
|
68
|
+
const record = new Map();
|
|
69
|
+
/** @type {Map<number, number>} per record word, which store last wrote it */
|
|
70
|
+
const origin = new Map();
|
|
71
|
+
/** @type {ParticleVectorPlace[]} */
|
|
72
|
+
const kills = [];
|
|
73
|
+
/** @type {number[]} */
|
|
74
|
+
const draws = [];
|
|
75
|
+
/** @type {number[]} */
|
|
76
|
+
const draw_lanes = [];
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The record as the section found it, over a run of words — one `ATTR` for the whole run, so that
|
|
80
|
+
* a `vec3` read out of the record is one value and not three to be glued together.
|
|
81
|
+
*
|
|
82
|
+
* @param {number} word
|
|
83
|
+
* @param {number} width
|
|
84
|
+
* @returns {ParticleVectorPlace[]}
|
|
85
|
+
*/
|
|
86
|
+
const found = (word, width) => {
|
|
87
|
+
const fresh = [];
|
|
88
|
+
|
|
89
|
+
for (let lane = 0; lane < width; lane++) {
|
|
90
|
+
if (initial.has(word + lane) || record.has(word + lane)) {
|
|
91
|
+
fresh.push(-1);
|
|
92
|
+
} else {
|
|
93
|
+
fresh.push(lane);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Only a run nothing has touched can be one load; anything else is read word by word, and
|
|
98
|
+
// whatever those turn out to be is the BUILD's business.
|
|
99
|
+
if (fresh.every(lane => lane >= 0)) {
|
|
100
|
+
const value = graph.make({ op: PV.ATTR, width, imm: [word] });
|
|
101
|
+
|
|
102
|
+
for (let lane = 0; lane < width; lane++) {
|
|
103
|
+
initial.set(word + lane, { value, lane });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const places = [];
|
|
108
|
+
|
|
109
|
+
for (let lane = 0; lane < width; lane++) {
|
|
110
|
+
const at = word + lane;
|
|
111
|
+
|
|
112
|
+
if (!initial.has(at)) {
|
|
113
|
+
initial.set(at, { value: graph.make({ op: PV.ATTR, width: 1, imm: [at] }), lane: 0 });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
places.push(record.get(at) ?? initial.get(at));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return places;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
for (let i = 0; i < instructions.length; i++) {
|
|
123
|
+
const instruction = decode_particle_instruction(instructions[i], i);
|
|
124
|
+
|
|
125
|
+
const { op, operation_width: width, write } = instruction;
|
|
126
|
+
|
|
127
|
+
if (op === VM_OP.HALT) {
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (op === VM_OP.NOP) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (write !== null && write.base + write.span > register_slots) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** @type {Array<{value: number, pattern: number}|null>} one per source slot */
|
|
140
|
+
const operands = [];
|
|
141
|
+
let refused = false;
|
|
142
|
+
|
|
143
|
+
for (const source of instruction.sources) {
|
|
144
|
+
if (source.kind === VM_KIND.IMM) {
|
|
145
|
+
const literal = vm_f32_value(source.word);
|
|
146
|
+
|
|
147
|
+
operands[source.operand] = {
|
|
148
|
+
value: graph.constant(literal),
|
|
149
|
+
pattern: pack_swizzle(0, 0, 0, 0),
|
|
150
|
+
};
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const places = [];
|
|
155
|
+
|
|
156
|
+
for (let lane = 0; lane < source.lanes; lane++) {
|
|
157
|
+
const slot = vm_operand_base(source.word) + swizzle_selector(source.pattern, lane);
|
|
158
|
+
|
|
159
|
+
if (slot < 0 || slot >= register_slots) {
|
|
160
|
+
refused = true;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
places.push(reg[slot]);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (refused) {
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
operands[source.operand] = read(graph, places);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (refused) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const places = evaluate(graph, instruction, operands, {
|
|
179
|
+
constants,
|
|
180
|
+
zero,
|
|
181
|
+
record,
|
|
182
|
+
origin,
|
|
183
|
+
found,
|
|
184
|
+
kills,
|
|
185
|
+
draws,
|
|
186
|
+
draw_lanes,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
if (places === null) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
for (let lane = 0; lane < places.length; lane++) {
|
|
194
|
+
reg[write.base + lane] = places[lane];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** @type {Array<{word: number, place: ParticleVectorPlace, origin: number}>} */
|
|
199
|
+
const stores = [];
|
|
200
|
+
|
|
201
|
+
for (let word = 0; word < PARTICLE_RECORD_WORD_COUNT; word++) {
|
|
202
|
+
const place = record.get(word);
|
|
203
|
+
|
|
204
|
+
if (place === undefined) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const was = initial.get(word);
|
|
209
|
+
|
|
210
|
+
if (was !== undefined && graph.find(was.value) === graph.find(place.value) && was.lane === place.lane) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
stores.push({ word, place, origin: origin.get(word) });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return { stores, kills, draw_count: draws.length, draws, draw_lanes };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* A run of places, as one source operand — or as a `BUILD` when they do not all come from one value.
|
|
222
|
+
*
|
|
223
|
+
* This is the whole of what keeping vectors buys, in one function. A frontend put a value in a run
|
|
224
|
+
* and its consumers read that run, so the places agree and the read is a swizzle: free. Where they do
|
|
225
|
+
* not agree, the copies are counted here, in the open.
|
|
226
|
+
*
|
|
227
|
+
* @param {import("./particle_vector_graph.js").ParticleVectorGraph} graph
|
|
228
|
+
* @param {ParticleVectorPlace[]} places one per lane read
|
|
229
|
+
* @returns {{value: number, pattern: number}}
|
|
230
|
+
*/
|
|
231
|
+
export function read(graph, places) {
|
|
232
|
+
const first = graph.find(places[0].value);
|
|
233
|
+
const together = places.every(place => graph.find(place.value) === first);
|
|
234
|
+
|
|
235
|
+
if (together && places.every(place => place.lane < VM_MAX_WIDTH)) {
|
|
236
|
+
return { value: first, pattern: selectors(places.map(place => place.lane)) };
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
value: graph.make({
|
|
241
|
+
op: PV.BUILD,
|
|
242
|
+
width: places.length,
|
|
243
|
+
children: places.map(place => place.value),
|
|
244
|
+
patterns: places.map(place => place.lane),
|
|
245
|
+
}),
|
|
246
|
+
pattern: VM_SWIZZLE_IDENTITY,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @param {number[]} lanes
|
|
252
|
+
* @returns {number} a swizzle reading those lanes, with the identity above them
|
|
253
|
+
*/
|
|
254
|
+
function selectors(lanes) {
|
|
255
|
+
return pack_swizzle(
|
|
256
|
+
lanes[0] ?? 0,
|
|
257
|
+
lanes[1] ?? 1,
|
|
258
|
+
lanes[2] ?? 2,
|
|
259
|
+
lanes[3] ?? 3
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* @param {import("./particle_vector_graph.js").ParticleVectorGraph} graph
|
|
265
|
+
* @param {number} value
|
|
266
|
+
* @param {number} width
|
|
267
|
+
* @returns {ParticleVectorPlace[]} the lanes of a value, as places
|
|
268
|
+
*/
|
|
269
|
+
function lanes_of(graph, value, width) {
|
|
270
|
+
return Array.from({ length: width }, (unused, lane) => ({ value, lane }));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* One instruction, as the places it leaves in its destination.
|
|
275
|
+
*
|
|
276
|
+
* @param {import("./particle_vector_graph.js").ParticleVectorGraph} graph
|
|
277
|
+
* @param {import("../particle_program_analysis.js").ParticleDecodedInstruction} instruction
|
|
278
|
+
* @param {Array<{value: number, pattern: number}|null>} operands
|
|
279
|
+
* @param {object} state
|
|
280
|
+
* @returns {ParticleVectorPlace[]|null}
|
|
281
|
+
*/
|
|
282
|
+
function evaluate(graph, instruction, operands, state) {
|
|
283
|
+
const { op, words, operation_width: width } = instruction;
|
|
284
|
+
const dest = vm_dest_width(op, instruction.width);
|
|
285
|
+
const semantics = vm_semantics_of(op);
|
|
286
|
+
const source = slot => operands[slot];
|
|
287
|
+
const node = shape => lanes_of(graph, graph.make(shape), shape.width);
|
|
288
|
+
|
|
289
|
+
switch (op) {
|
|
290
|
+
// A copy is not a value: it is the same value, read through a swizzle, and whoever reads the
|
|
291
|
+
// copy can read the original the same way.
|
|
292
|
+
case VM_OP.MOV: {
|
|
293
|
+
const from = source(0);
|
|
294
|
+
const places = [];
|
|
295
|
+
|
|
296
|
+
for (let lane = 0; lane < dest; lane++) {
|
|
297
|
+
places.push({ value: from.value, lane: swizzle_selector(from.pattern, lane) });
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return places;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
case VM_OP.LOAD_CONST: {
|
|
304
|
+
if (words[1] + dest > state.constants.length) {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const values = [];
|
|
309
|
+
|
|
310
|
+
for (let lane = 0; lane < dest; lane++) {
|
|
311
|
+
values.push(state.constants[words[1] + lane]);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return lanes_of(graph, graph.constant(...values), dest);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
case VM_OP.LOAD_ATTR: {
|
|
318
|
+
if (words[1] + Math.min(dest, words[2]) > PARTICLE_RECORD_WORD_COUNT) {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const held = state.found(words[1], Math.min(dest, words[2]));
|
|
323
|
+
const places = [];
|
|
324
|
+
|
|
325
|
+
for (let lane = 0; lane < dest; lane++) {
|
|
326
|
+
// Lanes past the component count are the zero an over-wide load reads on both
|
|
327
|
+
// executors.
|
|
328
|
+
places.push(lane < words[2] ? held[lane] : state.zero);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return places;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
case VM_OP.STORE_ATTR: {
|
|
335
|
+
if (words[2] + words[3] > PARTICLE_RECORD_WORD_COUNT) {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const from = source(0);
|
|
340
|
+
|
|
341
|
+
for (let lane = 0; lane < words[3]; lane++) {
|
|
342
|
+
state.record.set(words[2] + lane, {
|
|
343
|
+
value: from.value,
|
|
344
|
+
lane: swizzle_selector(from.pattern, lane),
|
|
345
|
+
});
|
|
346
|
+
state.origin.set(words[2] + lane, instruction.index);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return [];
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Never folded past the builtin's component count: `EMITTER_POSITION` reads `1.0` in its
|
|
353
|
+
// fourth lane on both executors.
|
|
354
|
+
case VM_OP.LOAD_BUILTIN:
|
|
355
|
+
return node({ op, width: dest, imm: [words[1]] });
|
|
356
|
+
|
|
357
|
+
case VM_OP.KILL: {
|
|
358
|
+
const from = source(0);
|
|
359
|
+
const place = { value: from.value, lane: swizzle_selector(from.pattern, 0) };
|
|
360
|
+
const literal = graph.constant_at(place.value, place.lane);
|
|
361
|
+
|
|
362
|
+
// A condition that cannot be positive is a kill that never fires.
|
|
363
|
+
if (literal !== null && !(literal > 0)) {
|
|
364
|
+
return [];
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (!state.kills.some(other => graph.find(other.value) === graph.find(place.value) && other.lane === place.lane)) {
|
|
368
|
+
state.kills.push(place);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return [];
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
case VM_OP.RANDOM: {
|
|
375
|
+
const first = state.draws.length;
|
|
376
|
+
const value = graph.make({ op, width: dest, imm: [first] });
|
|
377
|
+
|
|
378
|
+
for (let lane = 0; lane < dest; lane++) {
|
|
379
|
+
state.draws.push(value);
|
|
380
|
+
state.draw_lanes.push(lane);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return lanes_of(graph, value, dest);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Every lane is the same sample, so one lane holds it and a consumer reading it wide reads a
|
|
387
|
+
// broadcast.
|
|
388
|
+
case VM_OP.CURVE: {
|
|
389
|
+
const value = graph.make({
|
|
390
|
+
op,
|
|
391
|
+
width: 1,
|
|
392
|
+
children: [source(1).value],
|
|
393
|
+
patterns: [source(1).pattern],
|
|
394
|
+
imm: [words[1]],
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
return Array.from({ length: dest }, () => ({ value, lane: 0 }));
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
default: {
|
|
401
|
+
if (semantics.side_effects) {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// An instruction that merely copies one of its operands is not a value — it is that
|
|
406
|
+
// operand, read the way it was already being read. Recognised here rather than as a graph
|
|
407
|
+
// rule because a view is something only an instruction's RESULT can be.
|
|
408
|
+
const copied = identity_of(graph, op, operands, width);
|
|
409
|
+
|
|
410
|
+
if (copied !== null) {
|
|
411
|
+
return Array.from({ length: dest }, (unused, lane) => ({
|
|
412
|
+
value: copied.value,
|
|
413
|
+
lane: swizzle_selector(copied.pattern, lane),
|
|
414
|
+
}));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const children = [];
|
|
418
|
+
const patterns = [];
|
|
419
|
+
|
|
420
|
+
for (let slot = 0; slot < 3; slot++) {
|
|
421
|
+
if (operands[slot] !== undefined) {
|
|
422
|
+
children.push(operands[slot].value);
|
|
423
|
+
patterns.push(operands[slot].pattern);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// And an instruction only SOME of whose lanes are copies is the narrower instruction over
|
|
428
|
+
// the lanes that are left, with those lanes still read where they already were.
|
|
429
|
+
const copies = dest === width ? identity_lanes(graph, op, operands, width) : null;
|
|
430
|
+
|
|
431
|
+
if (copies !== null) {
|
|
432
|
+
const keep = [];
|
|
433
|
+
|
|
434
|
+
for (let lane = 0; lane < width; lane++) {
|
|
435
|
+
if (copies[lane] < 0) {
|
|
436
|
+
keep.push(lane);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const narrowed = keep.length === 0 ? -1 : graph.make({
|
|
441
|
+
op,
|
|
442
|
+
width: keep.length,
|
|
443
|
+
operand_width: keep.length,
|
|
444
|
+
children,
|
|
445
|
+
patterns: patterns.map(pattern => pack_swizzle(
|
|
446
|
+
...[0, 1, 2, 3].map(lane =>
|
|
447
|
+
swizzle_selector(pattern, keep[Math.min(lane, keep.length - 1)]))
|
|
448
|
+
)),
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
return Array.from({ length: dest }, (unused, lane) => (copies[lane] >= 0
|
|
452
|
+
? {
|
|
453
|
+
value: operands[copies[lane]].value,
|
|
454
|
+
lane: swizzle_selector(operands[copies[lane]].pattern, lane),
|
|
455
|
+
}
|
|
456
|
+
: { value: narrowed, lane: keep.indexOf(lane) }));
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return node({ op, width: dest, operand_width: width, children, patterns });
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Give the groups an order and a register file, and write the instructions.
|
|
3
|
+
*
|
|
4
|
+
* By the time this runs there is nothing left to decide about WHAT the program computes — only when
|
|
5
|
+
* each instruction runs and which slots it uses. Those are the two halves of the register-count
|
|
6
|
+
* problem, and the notes' pipeline is exactly this: schedule for the fewest values alive at once,
|
|
7
|
+
* then colour, which for straight-line code is an interval graph and so optimal for a fixed order.
|
|
8
|
+
*
|
|
9
|
+
* ## Ordering
|
|
10
|
+
*
|
|
11
|
+
* The value graph left almost nothing to obey. There are no anti-dependencies at all — a value is
|
|
12
|
+
* not a register until this module makes it one, so the write-after-read and write-after-write
|
|
13
|
+
* hazards that constrain `../pass_schedule.js` do not exist here. What remains is the true data
|
|
14
|
+
* dependencies and ONE chain: the RNG draws come off a sequence, so the `RANDOM` groups keep their
|
|
15
|
+
* order among themselves. Stores and kills are free to go anywhere after the values they read, which
|
|
16
|
+
* is the practical difference between the two optimizers' schedules — over there a store is a
|
|
17
|
+
* barrier nothing crosses.
|
|
18
|
+
*
|
|
19
|
+
* The order is chosen by the same backward greedy `../pass_schedule.js` uses: place last the
|
|
20
|
+
* instruction that leaves fewest slots alive above it. It is a greedy, and a greedy can be fooled;
|
|
21
|
+
* an exact minimum-register schedule is a constraint-programming problem, which is where the notes
|
|
22
|
+
* point next and where a solver would be needed.
|
|
23
|
+
*
|
|
24
|
+
* ## Colouring
|
|
25
|
+
*
|
|
26
|
+
* A group's run is live from where it is written to the last instruction that reads it, so the live
|
|
27
|
+
* ranges are intervals and the lowest-base first fit is the classic optimal left-edge colouring —
|
|
28
|
+
* for SCALARS. A run of two or more is a shape rather than a point and first fit is then a
|
|
29
|
+
* heuristic; the same caveat `../pass_allocate_registers.js` carries, and the reason it is worth
|
|
30
|
+
* running that pass over the result afterwards.
|
|
31
|
+
*
|
|
32
|
+
* One exception to "sources are read before the destination is written", which is otherwise true of
|
|
33
|
+
* every instruction in this ISA and is what lets a destination reuse a slot that dies at the same
|
|
34
|
+
* instruction: a GATHER is several `MOV`s, and the first of them would clobber a slot a later one
|
|
35
|
+
* still has to read. So a gather's run is allocated before its operands are released and never
|
|
36
|
+
* overlaps them.
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* @typedef {object} ParticleLoweredSection
|
|
40
|
+
* @property {InstructionStream} stream
|
|
41
|
+
* @property {number} peak the most slots alive at once, which is what the file has to hold
|
|
42
|
+
* @property {number[]} order the group indices, in the order they run
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* @param {import("./particle_vector_groups.js").ParticleValuePacking} packing
|
|
46
|
+
* @param {object} params
|
|
47
|
+
* @param {number} params.register_slots
|
|
48
|
+
* @param {function(number[]): number} params.intern_constant adds a run to the shared pool and
|
|
49
|
+
* returns its first word
|
|
50
|
+
* @returns {ParticleLoweredSection|null} `null` when the program does not fit the register file
|
|
51
|
+
*/
|
|
52
|
+
export function lower_particle_values(packing: import("./particle_vector_groups.js").ParticleValuePacking, { register_slots, intern_constant }: {
|
|
53
|
+
register_slots: number;
|
|
54
|
+
intern_constant: (arg0: number[]) => number;
|
|
55
|
+
}): ParticleLoweredSection | null;
|
|
56
|
+
/**
|
|
57
|
+
* Per group, the groups it must come after.
|
|
58
|
+
*
|
|
59
|
+
* @param {import("./particle_vector_groups.js").ParticleValueGroup[]} groups
|
|
60
|
+
* @returns {Set<number>[]}
|
|
61
|
+
*/
|
|
62
|
+
export function build_group_dependencies(groups: import("./particle_vector_groups.js").ParticleValueGroup[]): Set<number>[];
|
|
63
|
+
/**
|
|
64
|
+
* The order the groups run in: whichever of two candidate schedules holds fewer slots at once.
|
|
65
|
+
*
|
|
66
|
+
* The first is the section's own order, rebuilt — a forward topological walk that always takes the
|
|
67
|
+
* ready group whose work came earliest. It is not clever and it is not meant to be; it is the
|
|
68
|
+
* schedule the program arrived with, which is a schedule somebody's frontend already thought about,
|
|
69
|
+
* and it is what stops this stage from ever being the reason a program stopped fitting.
|
|
70
|
+
*
|
|
71
|
+
* The second is the backward greedy `../pass_schedule.js` uses: place last the group that leaves
|
|
72
|
+
* fewest slots alive above it. It wins on programs whose values were computed a long way from where
|
|
73
|
+
* they are used — which is most hand-lowered code — and loses on programs made of many independent
|
|
74
|
+
* chains, where the liveness measure is flat and it interleaves twelve noise samples that should
|
|
75
|
+
* have been done one at a time.
|
|
76
|
+
*
|
|
77
|
+
* Neither is the minimum. An exact minimum-register schedule of a DAG is NP-complete and the answer
|
|
78
|
+
* at this size is a constraint solver, which is the next thing the notes point at; measuring two
|
|
79
|
+
* cheap orders and keeping the better is what is here instead, and it is at least never worse than
|
|
80
|
+
* the program's own.
|
|
81
|
+
*
|
|
82
|
+
* @param {import("./particle_vector_groups.js").ParticleValueGroup[]} groups
|
|
83
|
+
* @returns {number[]} group indices, in the order they run
|
|
84
|
+
*/
|
|
85
|
+
export function schedule_groups(groups: import("./particle_vector_groups.js").ParticleValueGroup[]): number[];
|
|
86
|
+
/**
|
|
87
|
+
* The most slots an order holds at once — what the register file has to be.
|
|
88
|
+
*
|
|
89
|
+
* @param {import("./particle_vector_groups.js").ParticleValueGroup[]} groups
|
|
90
|
+
* @param {number[]} order
|
|
91
|
+
* @returns {number}
|
|
92
|
+
*/
|
|
93
|
+
export function peak_slots(groups: import("./particle_vector_groups.js").ParticleValueGroup[], order: number[]): number;
|
|
94
|
+
/**
|
|
95
|
+
* Give each group's run the lowest base that is free for as long as it lives.
|
|
96
|
+
*
|
|
97
|
+
* @param {import("./particle_vector_groups.js").ParticleValueGroup[]} groups
|
|
98
|
+
* @param {number[]} order
|
|
99
|
+
* @param {number} register_slots
|
|
100
|
+
* @param {number[][]} [coalitions] runs that have to end up end to end, in that order
|
|
101
|
+
* @returns {Int32Array|null} per group, the slot its run starts at; `null` when the file is too small
|
|
102
|
+
*/
|
|
103
|
+
export function allocate_groups(groups: import("./particle_vector_groups.js").ParticleValueGroup[], order: number[], register_slots: number, coalitions?: number[][]): Int32Array | null;
|
|
104
|
+
export type ParticleLoweredSection = {
|
|
105
|
+
stream: InstructionStream;
|
|
106
|
+
/**
|
|
107
|
+
* the most slots alive at once, which is what the file has to hold
|
|
108
|
+
*/
|
|
109
|
+
peak: number;
|
|
110
|
+
/**
|
|
111
|
+
* the group indices, in the order they run
|
|
112
|
+
*/
|
|
113
|
+
order: number[];
|
|
114
|
+
};
|
|
115
|
+
import { InstructionStream } from "../../isa/InstructionStream.js";
|
|
116
|
+
//# sourceMappingURL=particle_vector_lower.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"particle_vector_lower.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,+CAPW,OAAO,6BAA6B,EAAE,oBAAoB;IAE3C,cAAc,EAA7B,MAAM;IAC6B,eAAe,SAAzC,MAAM,EAAE,KAAG,MAAM;IAExB,sBAAsB,GAAC,IAAI,CAiBvC;AAED;;;;;GAKG;AACH,iDAHW,OAAO,6BAA6B,EAAE,kBAAkB,EAAE,GACxD,IAAI,MAAM,CAAC,EAAE,CA0CzB;AAaD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wCAHW,OAAO,6BAA6B,EAAE,kBAAkB,EAAE,GACxD,MAAM,EAAE,CAoCpB;AAqGD;;;;;;GAMG;AACH,mCAJW,OAAO,6BAA6B,EAAE,kBAAkB,EAAE,SAC1D,MAAM,EAAE,GACN,MAAM,CAoClB;AAkID;;;;;;;;GAQG;AACH,wCANW,OAAO,6BAA6B,EAAE,kBAAkB,EAAE,SAC1D,MAAM,EAAE,kBACR,MAAM,eACN,MAAM,EAAE,EAAE,GACR,UAAU,GAAC,IAAI,CAoE3B;;YA5ea,iBAAiB;;;;UACjB,MAAM;;;;WACN,MAAM,EAAE;;kCA9CY,gCAAgC"}
|