@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
|
@@ -6,17 +6,28 @@ import {
|
|
|
6
6
|
} from "../ParticleConstants.js";
|
|
7
7
|
import { ParticleProgram } from "./ParticleProgram.js";
|
|
8
8
|
import {
|
|
9
|
+
pack_swizzle,
|
|
10
|
+
swizzle_selector,
|
|
9
11
|
VM_BUILTIN,
|
|
10
12
|
VM_ISA,
|
|
13
|
+
VM_KIND,
|
|
11
14
|
VM_MAX_WIDTH,
|
|
12
15
|
VM_OP,
|
|
13
16
|
VM_OPERAND,
|
|
17
|
+
VM_SWIZZLE_BROADCAST,
|
|
14
18
|
VM_WIDTH,
|
|
19
|
+
vm_decode_dst,
|
|
20
|
+
vm_decode_kind,
|
|
15
21
|
vm_decode_op,
|
|
16
22
|
vm_decode_width,
|
|
17
|
-
|
|
23
|
+
vm_f32_bits,
|
|
24
|
+
vm_f32_value,
|
|
25
|
+
vm_operand_base,
|
|
26
|
+
vm_operand_pattern,
|
|
18
27
|
vm_operation_width,
|
|
19
|
-
|
|
28
|
+
vm_pack_instruction,
|
|
29
|
+
vm_register,
|
|
30
|
+
vm_visit_register_runs,
|
|
20
31
|
} from "./ParticleVMISA.js";
|
|
21
32
|
|
|
22
33
|
/**
|
|
@@ -42,12 +53,13 @@ import {
|
|
|
42
53
|
* .init ; section — everything until the next section directive
|
|
43
54
|
* LOAD_BUILTIN.3 r0, EMITTER_POSITION
|
|
44
55
|
* RANDOM.2 r1
|
|
45
|
-
*
|
|
56
|
+
* MUL.2 r1, r1, #0.5 ; a literal where a register could stand
|
|
46
57
|
* STORE_ATTR r1, @1, 3 ; store r1 into the 3-component attribute at record word 1
|
|
47
58
|
*
|
|
48
59
|
* .update
|
|
49
60
|
* LOAD_ATTR.1 r0, @7, 1
|
|
50
61
|
* CMP_GE.1 r0, r0, r1
|
|
62
|
+
* MOV.3 r2, r0.xxx ; a register read through a swizzle: lane 0 three times
|
|
51
63
|
* KILL r0
|
|
52
64
|
* ```
|
|
53
65
|
*
|
|
@@ -62,16 +74,24 @@ import {
|
|
|
62
74
|
*
|
|
63
75
|
* | role | spelling | example |
|
|
64
76
|
* |---|---|---|
|
|
65
|
-
* |
|
|
77
|
+
* | destination | `r<slot>` | `r3` |
|
|
78
|
+
* | register source | `r<slot>`, optionally `.<selectors>` | `r3`, `r3.yyy`, `r0.zyx` |
|
|
79
|
+
* | literal source | `#<float>` | `#1.5` |
|
|
66
80
|
* | constant-pool word | `c<word>` | `c0` |
|
|
67
81
|
* | attribute word offset | `@<word>` | `@7` |
|
|
68
82
|
* | attribute component count | a bare integer `1..4` | `3` |
|
|
69
83
|
* | builtin | a {@link VM_BUILTIN} name | `EMITTER_POSITION` |
|
|
70
84
|
* | curve handle | `k<handle>` | `k2` |
|
|
71
|
-
* | swizzle pattern | `.<four of xyzw>` | `.xxyz` |
|
|
72
85
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
86
|
+
* A register source's selectors say which lane of the value each lane of the instruction reads, one
|
|
87
|
+
* letter of `xyzw` per lane the instruction spans; left off, lane `c` reads lane `c`. A literal is
|
|
88
|
+
* the same value in every lane. The destination is only ever a plain register.
|
|
89
|
+
*
|
|
90
|
+
* ## What older text still means
|
|
91
|
+
*
|
|
92
|
+
* Two mnemonics that were opcodes are now spellings of an operand, and documents that carry them read
|
|
93
|
+
* as the instruction they meant: `SWIZZLE.n rd, rs, .xyzw` is `MOV.n rd, rs.xyzw`, and `SCALE.n rd,
|
|
94
|
+
* rv, rs` is `MUL.n rd, rv, rs.xxxx`. The disassembler never writes either.
|
|
75
95
|
*/
|
|
76
96
|
|
|
77
97
|
/** Section directive introducing the INIT stream. @type {string} */
|
|
@@ -86,11 +106,12 @@ export const PARTICLE_ASSEMBLY_DIRECTIVE_REGISTERS = ".registers";
|
|
|
86
106
|
/** Directive declaring one constant-pool entry. @type {string} */
|
|
87
107
|
export const PARTICLE_ASSEMBLY_DIRECTIVE_CONST = ".const";
|
|
88
108
|
|
|
109
|
+
/** Opens a literal in a register slot: `#1.5`. @type {string} */
|
|
110
|
+
export const PARTICLE_ASSEMBLY_IMMEDIATE_PREFIX = "#";
|
|
111
|
+
|
|
89
112
|
/**
|
|
90
|
-
* Separates a mnemonic from the lane count it spans: `ADD.3`.
|
|
91
|
-
*
|
|
92
|
-
* The same character opens a directive and a swizzle pattern, but never in this position — a line
|
|
93
|
-
* starts with either a directive or a mnemonic, and a swizzle is an operand.
|
|
113
|
+
* Separates a mnemonic from the lane count it spans: `ADD.3`. Also separates a register from its
|
|
114
|
+
* selectors: `r3.yyy`. The same character opens a directive, but never in either of those positions.
|
|
94
115
|
*
|
|
95
116
|
* @type {string}
|
|
96
117
|
*/
|
|
@@ -104,18 +125,21 @@ export const PARTICLE_ASSEMBLY_WIDTH_SEPARATOR = ".";
|
|
|
104
125
|
* a bound the parser tries to allocate that pool and takes the page with it, which is a worse answer
|
|
105
126
|
* to a typo than a marker on the line.
|
|
106
127
|
*
|
|
107
|
-
* Generous against any real program: an effect's constants are its literals, and the whole
|
|
108
|
-
* instruction budget is {@link PARTICLE_VM_MAX_INSTRUCTIONS} per section.
|
|
109
|
-
*
|
|
110
128
|
* @type {number}
|
|
111
129
|
*/
|
|
112
130
|
export const PARTICLE_ASSEMBLY_MAX_CONSTANTS = 4096;
|
|
113
131
|
|
|
132
|
+
/** Lane selector characters, indexed by the 2-bit selector value a swizzle packs. @type {string} */
|
|
133
|
+
const SWIZZLE_LANES = "xyzw";
|
|
134
|
+
|
|
114
135
|
/**
|
|
115
|
-
*
|
|
116
|
-
* @type {string}
|
|
136
|
+
* Mnemonics that were opcodes and are now operand spellings, read for the documents that carry them.
|
|
137
|
+
* @type {Map<string, {op: number, form: string}>}
|
|
117
138
|
*/
|
|
118
|
-
const
|
|
139
|
+
const LEGACY_MNEMONICS = new Map([
|
|
140
|
+
["SWIZZLE", { op: VM_OP.MOV, form: "swizzle" }],
|
|
141
|
+
["SCALE", { op: VM_OP.MUL, form: "scale" }],
|
|
142
|
+
]);
|
|
119
143
|
|
|
120
144
|
/**
|
|
121
145
|
* Mnemonic -> opcode, derived from {@link VM_ISA} so the two cannot drift.
|
|
@@ -154,6 +178,10 @@ const BUILTIN_NAME_BY_ID = invert(VM_BUILTIN);
|
|
|
154
178
|
* @property {string} message
|
|
155
179
|
*/
|
|
156
180
|
|
|
181
|
+
// ---------------------------------------------------------------------------------------------
|
|
182
|
+
// Disassembly
|
|
183
|
+
// ---------------------------------------------------------------------------------------------
|
|
184
|
+
|
|
157
185
|
/**
|
|
158
186
|
* Render a compiled program as assembly text.
|
|
159
187
|
*
|
|
@@ -216,13 +244,14 @@ function disassemble_instruction(words, base) {
|
|
|
216
244
|
if (meta === undefined) {
|
|
217
245
|
// Not reachable from a validated program, but a disassembler that throws is useless for
|
|
218
246
|
// looking at the thing that went wrong.
|
|
219
|
-
return `; unknown opcode ${op} [${words[base + 1]}, ${words[base + 2]}, ${words[base + 3]}
|
|
247
|
+
return `; unknown opcode ${op} [${words[base + 1]}, ${words[base + 2]}, ${words[base + 3]}]`;
|
|
220
248
|
}
|
|
221
249
|
|
|
250
|
+
const operation_width = vm_operation_width(op, width);
|
|
222
251
|
const operands = [];
|
|
223
252
|
|
|
224
253
|
if (meta.dst) {
|
|
225
|
-
operands.push(`r${
|
|
254
|
+
operands.push(`r${vm_decode_dst(word0)}`);
|
|
226
255
|
}
|
|
227
256
|
|
|
228
257
|
for (let slot = 0; slot < 3; slot++) {
|
|
@@ -232,7 +261,15 @@ function disassemble_instruction(words, base) {
|
|
|
232
261
|
continue;
|
|
233
262
|
}
|
|
234
263
|
|
|
235
|
-
|
|
264
|
+
const word = words[base + 1 + slot];
|
|
265
|
+
|
|
266
|
+
if (role !== VM_OPERAND.REG) {
|
|
267
|
+
operands.push(format_operand(role, word));
|
|
268
|
+
} else if (vm_decode_kind(word0, slot) === VM_KIND.IMM) {
|
|
269
|
+
operands.push(`${PARTICLE_ASSEMBLY_IMMEDIATE_PREFIX}${format_float(vm_f32_value(word))}`);
|
|
270
|
+
} else {
|
|
271
|
+
operands.push(format_register(word, meta.scalar_operands.includes(slot) ? 1 : operation_width));
|
|
272
|
+
}
|
|
236
273
|
}
|
|
237
274
|
|
|
238
275
|
const mnemonic = meta.name + format_width_suffix(op, meta, width);
|
|
@@ -262,15 +299,36 @@ function format_width_suffix(op, meta, width) {
|
|
|
262
299
|
}
|
|
263
300
|
|
|
264
301
|
/**
|
|
265
|
-
*
|
|
302
|
+
* A register source: its slot, and the selectors of the lanes read wherever they are not the lane
|
|
303
|
+
* itself.
|
|
304
|
+
*
|
|
305
|
+
* @param {number} word a register operand
|
|
306
|
+
* @param {number} lanes lanes the instruction reads of it
|
|
307
|
+
* @returns {string}
|
|
308
|
+
*/
|
|
309
|
+
function format_register(word, lanes) {
|
|
310
|
+
const pattern = vm_operand_pattern(word);
|
|
311
|
+
|
|
312
|
+
let identity = true;
|
|
313
|
+
let selectors = "";
|
|
314
|
+
|
|
315
|
+
for (let lane = 0; lane < lanes; lane++) {
|
|
316
|
+
const selector = swizzle_selector(pattern, lane);
|
|
317
|
+
|
|
318
|
+
identity = identity && selector === lane;
|
|
319
|
+
selectors += SWIZZLE_LANES.charAt(selector);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return `r${vm_operand_base(word)}${identity ? "" : PARTICLE_ASSEMBLY_WIDTH_SEPARATOR + selectors}`;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* @param {string} role a {@link VM_OPERAND} value other than the register one
|
|
266
327
|
* @param {number} value
|
|
267
328
|
* @returns {string}
|
|
268
329
|
*/
|
|
269
330
|
function format_operand(role, value) {
|
|
270
331
|
switch (role) {
|
|
271
|
-
case VM_OPERAND.REG:
|
|
272
|
-
case VM_OPERAND.DST:
|
|
273
|
-
return `r${value}`;
|
|
274
332
|
case VM_OPERAND.CONST:
|
|
275
333
|
return `c${value}`;
|
|
276
334
|
case VM_OPERAND.ATTR_OFFSET:
|
|
@@ -281,27 +339,11 @@ function format_operand(role, value) {
|
|
|
281
339
|
return BUILTIN_NAME_BY_ID.get(value) ?? String(value);
|
|
282
340
|
case VM_OPERAND.CURVE:
|
|
283
341
|
return `k${value}`;
|
|
284
|
-
case VM_OPERAND.SWIZZLE:
|
|
285
|
-
return format_swizzle(value);
|
|
286
342
|
default:
|
|
287
343
|
return String(value);
|
|
288
344
|
}
|
|
289
345
|
}
|
|
290
346
|
|
|
291
|
-
/**
|
|
292
|
-
* @param {number} packed four 2-bit lane selectors
|
|
293
|
-
* @returns {string} `.xyzw` form
|
|
294
|
-
*/
|
|
295
|
-
function format_swizzle(packed) {
|
|
296
|
-
let result = ".";
|
|
297
|
-
|
|
298
|
-
for (let lane = 0; lane < 4; lane++) {
|
|
299
|
-
result += SWIZZLE_LANES.charAt((packed >>> (lane * 2)) & 3);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
return result;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
347
|
/**
|
|
306
348
|
* A float spelled so it reads back as itself.
|
|
307
349
|
*
|
|
@@ -335,6 +377,10 @@ function format_float(value) {
|
|
|
335
377
|
return String(value);
|
|
336
378
|
}
|
|
337
379
|
|
|
380
|
+
// ---------------------------------------------------------------------------------------------
|
|
381
|
+
// Parsing
|
|
382
|
+
// ---------------------------------------------------------------------------------------------
|
|
383
|
+
|
|
338
384
|
/**
|
|
339
385
|
* Read assembly text into a program, reporting every problem rather than stopping at the first.
|
|
340
386
|
*
|
|
@@ -353,7 +399,7 @@ export function parse_particle_assembly(text) {
|
|
|
353
399
|
|
|
354
400
|
const report = (line, message) => diagnostics.push({ line, message });
|
|
355
401
|
|
|
356
|
-
/** @type {number[]} flat constant pool,
|
|
402
|
+
/** @type {number[]} flat constant pool, one float per word */
|
|
357
403
|
const constants = [];
|
|
358
404
|
/** @type {Set<number>} constant indices a `.const` directive has already claimed */
|
|
359
405
|
const declared_constants = new Set();
|
|
@@ -446,7 +492,7 @@ export function parse_particle_assembly(text) {
|
|
|
446
492
|
}
|
|
447
493
|
|
|
448
494
|
// dense constant indices: c0..cN-1 with nothing missing, so a pool index means the same thing
|
|
449
|
-
// here as it does in the
|
|
495
|
+
// here as it does in the heap
|
|
450
496
|
for (let i = 0; i < constants.length; i++) {
|
|
451
497
|
if (!declared_constants.has(i)) {
|
|
452
498
|
report(0, `Constant c${i} is referenced by the pool's length but never declared`);
|
|
@@ -456,7 +502,7 @@ export function parse_particle_assembly(text) {
|
|
|
456
502
|
const register_count = declared_register_count === -1 ? register_high_water : declared_register_count;
|
|
457
503
|
|
|
458
504
|
if (register_count > PARTICLE_VM_REGISTER_SLOTS) {
|
|
459
|
-
report(0, `
|
|
505
|
+
report(0, `A VM instruction can address ${PARTICLE_VM_REGISTER_SLOTS} slots, the program asks for ${register_count}`);
|
|
460
506
|
}
|
|
461
507
|
|
|
462
508
|
const constant_word_count = constants.length;
|
|
@@ -532,11 +578,12 @@ function check_stream_references(stream, register_count, constant_word_count, re
|
|
|
532
578
|
for (let i = 0; i < instruction_count; i++) {
|
|
533
579
|
const base = i * PARTICLE_VM_INSTRUCTION_WORDS;
|
|
534
580
|
const line = stream.lines[i];
|
|
535
|
-
const
|
|
581
|
+
const op = vm_decode_op(words[base]);
|
|
582
|
+
const meta = VM_ISA.get(op);
|
|
536
583
|
|
|
537
584
|
// An operand of width w occupies w consecutive slots, so it is the END of the run that has
|
|
538
585
|
// to be inside the file: `MOV.4 r30` starts inside a 32-slot file and finishes outside one.
|
|
539
|
-
|
|
586
|
+
vm_visit_register_runs(words, base, (index, span) => {
|
|
540
587
|
if (index + span <= register_count) {
|
|
541
588
|
return;
|
|
542
589
|
}
|
|
@@ -550,29 +597,27 @@ function check_stream_references(stream, register_count, constant_word_count, re
|
|
|
550
597
|
);
|
|
551
598
|
});
|
|
552
599
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
if (role === VM_OPERAND.CONST) {
|
|
558
|
-
// The load reads one word per lane, so the whole run has to be inside the pool.
|
|
559
|
-
const span = vm_operation_width(vm_decode_op(words[base]), vm_decode_width(words[base]));
|
|
600
|
+
if (op === VM_OP.LOAD_CONST) {
|
|
601
|
+
// The load reads one word per lane, so the whole run has to be inside the pool.
|
|
602
|
+
const first = words[base + 1];
|
|
603
|
+
const span = vm_operation_width(op, vm_decode_width(words[base]));
|
|
560
604
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
}
|
|
605
|
+
if (first + span > constant_word_count) {
|
|
606
|
+
report(
|
|
607
|
+
line,
|
|
608
|
+
`c${first} reads ${span} word${span === 1 ? "" : "s"}, past the end of the `
|
|
609
|
+
+ `${constant_word_count}-word constant pool`
|
|
610
|
+
);
|
|
568
611
|
}
|
|
569
612
|
}
|
|
570
613
|
|
|
571
614
|
// An attribute access past the end of a record is not caught by GPU robustness: the address
|
|
572
615
|
// still lands inside the pool buffer, and reads or corrupts the NEXT particle's record.
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
616
|
+
const offset_slot = meta.operands.indexOf(VM_OPERAND.ATTR_OFFSET);
|
|
617
|
+
|
|
618
|
+
if (offset_slot !== -1) {
|
|
619
|
+
const offset = words[base + 1 + offset_slot];
|
|
620
|
+
const components = words[base + 2 + offset_slot];
|
|
576
621
|
|
|
577
622
|
if (offset + components > PARTICLE_RECORD_WORD_COUNT) {
|
|
578
623
|
report(
|
|
@@ -671,6 +716,14 @@ function parse_directive(line, line_number, report) {
|
|
|
671
716
|
return null;
|
|
672
717
|
}
|
|
673
718
|
|
|
719
|
+
/**
|
|
720
|
+
* @typedef {object} ParsedOperand
|
|
721
|
+
* @property {number} kind a {@link VM_KIND}: `REG` or `IMM` for a register-role slot, `NONE` for any other
|
|
722
|
+
* @property {number} word the operand word
|
|
723
|
+
* @property {number} [selectors] for a register written with selectors, how many the text spelled
|
|
724
|
+
* @property {string} [token] the text the operand was read from, for messages
|
|
725
|
+
*/
|
|
726
|
+
|
|
674
727
|
/**
|
|
675
728
|
* @param {string} line already stripped of comments and trimmed
|
|
676
729
|
* @param {number} line_number
|
|
@@ -688,7 +741,8 @@ function parse_instruction(line, line_number, report) {
|
|
|
688
741
|
const mnemonic = separator === -1 ? head : head.slice(0, separator);
|
|
689
742
|
const width_text = separator === -1 ? "" : head.slice(separator + 1);
|
|
690
743
|
|
|
691
|
-
const
|
|
744
|
+
const legacy = LEGACY_MNEMONICS.get(mnemonic) ?? null;
|
|
745
|
+
const opcode = legacy === null ? OPCODE_BY_NAME.get(mnemonic) : legacy.op;
|
|
692
746
|
|
|
693
747
|
if (opcode === undefined) {
|
|
694
748
|
report(line_number, `Unknown instruction '${mnemonic}'`);
|
|
@@ -723,11 +777,88 @@ function parse_instruction(line, line_number, report) {
|
|
|
723
777
|
|
|
724
778
|
const tokens = rest.split(",").map(t => t.trim()).filter(t => t !== "");
|
|
725
779
|
|
|
726
|
-
|
|
780
|
+
const parsed = legacy === null
|
|
781
|
+
? parse_operands(meta, tokens, line_number, report)
|
|
782
|
+
: parse_legacy_operands(legacy.form, mnemonic, tokens, line_number, report);
|
|
783
|
+
|
|
784
|
+
if (parsed === null) {
|
|
785
|
+
return null;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
const { dst, sources } = parsed;
|
|
789
|
+
|
|
790
|
+
// The attribute ops measure themselves in components unless the text says otherwise: a load may
|
|
791
|
+
// be widened past its attribute (the lanes beyond read zero), a store may not — it writes one
|
|
792
|
+
// record word per lane, so its width IS the component count.
|
|
793
|
+
if (opcode === VM_OP.LOAD_ATTR && width_text === "") {
|
|
794
|
+
width = sources[1].word;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
if (opcode === VM_OP.STORE_ATTR) {
|
|
798
|
+
if (width_text !== "" && width !== sources[2].word) {
|
|
799
|
+
report(line_number, `STORE_ATTR width ${width} must equal its component count ${sources[2].word}`);
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
width = sources[2].word;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Selectors are written one per lane read, and the lane count is known only now that the width
|
|
807
|
+
// is: `r6.xx` on a three-lane read would otherwise quietly be `r6.xxz`.
|
|
808
|
+
const operation_width = vm_operation_width(opcode, width);
|
|
809
|
+
|
|
810
|
+
for (let slot = 0; slot < sources.length; slot++) {
|
|
811
|
+
const source = sources[slot];
|
|
812
|
+
const lanes = meta.scalar_operands.includes(slot) ? 1 : operation_width;
|
|
813
|
+
|
|
814
|
+
if (source.kind === VM_KIND.REG && source.selectors !== undefined && source.selectors > 0 && source.selectors !== lanes) {
|
|
815
|
+
report(
|
|
816
|
+
line_number,
|
|
817
|
+
`${meta.name} reads ${lanes} lane${lanes === 1 ? "" : "s"} of '${source.token}', `
|
|
818
|
+
+ `which names ${source.selectors} selector${source.selectors === 1 ? "" : "s"}; write one per lane`
|
|
819
|
+
);
|
|
820
|
+
return null;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
const words = vm_pack_instruction(
|
|
825
|
+
opcode,
|
|
826
|
+
width,
|
|
827
|
+
dst,
|
|
828
|
+
sources.map(source => source.kind),
|
|
829
|
+
sources.map(source => source.word)
|
|
830
|
+
);
|
|
831
|
+
|
|
832
|
+
// Registers are scalar slots, so what the file has to hold is where the widest operand ENDS.
|
|
833
|
+
// Sizing it by the largest index written down leaves a `RANDOM.3 r0` writing r1 and r2 outside
|
|
834
|
+
// the file it derived, which the interpreter reads back as zero and the reference as nothing.
|
|
835
|
+
let register_reach = 0;
|
|
836
|
+
|
|
837
|
+
vm_visit_register_runs(words, 0, (slot, span) => {
|
|
838
|
+
if (slot + span > register_reach) {
|
|
839
|
+
register_reach = slot + span;
|
|
840
|
+
}
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
return { words, register_reach };
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* The operands of an ordinary instruction, in the order they are written: the destination when the
|
|
848
|
+
* opcode has one, then every source whose role is not `NONE`.
|
|
849
|
+
*
|
|
850
|
+
* @param {object} meta the opcode's {@link VM_ISA} entry
|
|
851
|
+
* @param {string[]} tokens
|
|
852
|
+
* @param {number} line_number
|
|
853
|
+
* @param {function(number, string):void} report
|
|
854
|
+
* @returns {{dst: number, sources: ParsedOperand[]}|null}
|
|
855
|
+
*/
|
|
856
|
+
function parse_operands(meta, tokens, line_number, report) {
|
|
857
|
+
/** roles the written operands fill, in order */
|
|
727
858
|
const roles = [];
|
|
728
859
|
|
|
729
860
|
if (meta.dst) {
|
|
730
|
-
roles.push(
|
|
861
|
+
roles.push("dst");
|
|
731
862
|
}
|
|
732
863
|
|
|
733
864
|
for (let slot = 0; slot < 3; slot++) {
|
|
@@ -745,86 +876,181 @@ function parse_instruction(line, line_number, report) {
|
|
|
745
876
|
return null;
|
|
746
877
|
}
|
|
747
878
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
const words = [0, 0, 0, 0, 0];
|
|
751
|
-
|
|
879
|
+
let dst = 0;
|
|
880
|
+
const sources = [none(), none(), none()];
|
|
752
881
|
let slot_cursor = 0;
|
|
753
882
|
|
|
754
883
|
for (let i = 0; i < roles.length; i++) {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
if (value === null) {
|
|
759
|
-
return null;
|
|
760
|
-
}
|
|
884
|
+
if (roles[i] === "dst") {
|
|
885
|
+
dst = parse_destination(tokens[i], line_number, report);
|
|
761
886
|
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
} else {
|
|
765
|
-
// source slots are written in ISA order, skipping the ones marked NONE
|
|
766
|
-
while (meta.operands[slot_cursor] === VM_OPERAND.NONE) {
|
|
767
|
-
slot_cursor++;
|
|
887
|
+
if (dst === null) {
|
|
888
|
+
return null;
|
|
768
889
|
}
|
|
769
890
|
|
|
770
|
-
|
|
891
|
+
continue;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// source slots are written in ISA order, skipping the ones marked NONE
|
|
895
|
+
while (meta.operands[slot_cursor] === VM_OPERAND.NONE) {
|
|
771
896
|
slot_cursor++;
|
|
772
897
|
}
|
|
898
|
+
|
|
899
|
+
const operand = roles[i] === VM_OPERAND.REG
|
|
900
|
+
? parse_register_operand(tokens[i], line_number, report)
|
|
901
|
+
: parse_plain_operand(roles[i], tokens[i], line_number, report);
|
|
902
|
+
|
|
903
|
+
if (operand === null) {
|
|
904
|
+
return null;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
sources[slot_cursor] = operand;
|
|
908
|
+
slot_cursor++;
|
|
773
909
|
}
|
|
774
910
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
911
|
+
return { dst, sources };
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* The operands of a legacy mnemonic, rewritten as the instruction it now spells.
|
|
916
|
+
*
|
|
917
|
+
* `SWIZZLE rd, rs, .xyzw` reads its pattern into `rs`'s swizzle; `SCALE rd, rv, rs` reads `rs`
|
|
918
|
+
* through `.xxxx`. A literal in either source position is what it is — one value in every lane —
|
|
919
|
+
* and the pattern or broadcast changes nothing about it.
|
|
920
|
+
*
|
|
921
|
+
* @param {string} form `"swizzle"` or `"scale"`
|
|
922
|
+
* @param {string} mnemonic as written, for messages
|
|
923
|
+
* @param {string[]} tokens
|
|
924
|
+
* @param {number} line_number
|
|
925
|
+
* @param {function(number, string):void} report
|
|
926
|
+
* @returns {{dst: number, sources: ParsedOperand[]}|null}
|
|
927
|
+
*/
|
|
928
|
+
function parse_legacy_operands(form, mnemonic, tokens, line_number, report) {
|
|
929
|
+
if (tokens.length !== 3) {
|
|
930
|
+
report(line_number, `${mnemonic} takes 3 operands, got ${tokens.length}`);
|
|
931
|
+
return null;
|
|
780
932
|
}
|
|
781
933
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
934
|
+
const dst = parse_destination(tokens[0], line_number, report);
|
|
935
|
+
|
|
936
|
+
if (dst === null) {
|
|
937
|
+
return null;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
if (form === "swizzle") {
|
|
941
|
+
const source = parse_register_operand(tokens[1], line_number, report);
|
|
942
|
+
const pattern = parse_swizzle_pattern(tokens[2]);
|
|
943
|
+
|
|
944
|
+
if (source === null) {
|
|
785
945
|
return null;
|
|
786
946
|
}
|
|
787
947
|
|
|
788
|
-
|
|
948
|
+
if (pattern === null) {
|
|
949
|
+
report(line_number, `Expected a swizzle like '.xyzw', got '${tokens[2]}'`);
|
|
950
|
+
return null;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
return { dst, sources: [with_pattern(source, pattern), none(), none()] };
|
|
789
954
|
}
|
|
790
955
|
|
|
791
|
-
|
|
956
|
+
const vector = parse_register_operand(tokens[1], line_number, report);
|
|
957
|
+
const scalar = parse_register_operand(tokens[2], line_number, report);
|
|
792
958
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
let register_reach = 0;
|
|
959
|
+
if (vector === null || scalar === null) {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
797
962
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
register_reach = slot + span;
|
|
801
|
-
}
|
|
802
|
-
});
|
|
963
|
+
return { dst, sources: [vector, with_pattern(scalar, VM_SWIZZLE_BROADCAST), none()] };
|
|
964
|
+
}
|
|
803
965
|
|
|
804
|
-
|
|
966
|
+
/** @returns {ParsedOperand} the operand of an unused slot */
|
|
967
|
+
function none() {
|
|
968
|
+
return { kind: VM_KIND.NONE, word: 0 };
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* @param {ParsedOperand} operand
|
|
973
|
+
* @param {number} pattern
|
|
974
|
+
* @returns {ParsedOperand} a register operand read through `pattern`; a literal, unchanged
|
|
975
|
+
*/
|
|
976
|
+
function with_pattern(operand, pattern) {
|
|
977
|
+
return operand.kind === VM_KIND.REG
|
|
978
|
+
? { kind: VM_KIND.REG, word: vm_register(vm_operand_base(operand.word), pattern), token: operand.token }
|
|
979
|
+
: operand;
|
|
805
980
|
}
|
|
806
981
|
|
|
807
982
|
/**
|
|
808
|
-
* @param {string} role
|
|
809
983
|
* @param {string} token
|
|
810
984
|
* @param {number} line_number
|
|
811
985
|
* @param {function(number, string):void} report
|
|
812
|
-
* @returns {number|null}
|
|
986
|
+
* @returns {number|null} the destination register
|
|
813
987
|
*/
|
|
814
|
-
function
|
|
815
|
-
|
|
816
|
-
case VM_OPERAND.DST:
|
|
817
|
-
case VM_OPERAND.REG: {
|
|
818
|
-
const index = parse_prefixed(token, "r");
|
|
988
|
+
function parse_destination(token, line_number, report) {
|
|
989
|
+
const index = parse_prefixed(token, "r");
|
|
819
990
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
991
|
+
if (index === null) {
|
|
992
|
+
report(line_number, `A destination is a register like 'r0', got '${token}'`);
|
|
993
|
+
return null;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
return index;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
/**
|
|
1000
|
+
* An operand in a register slot: a register, optionally read through selectors, or a literal.
|
|
1001
|
+
*
|
|
1002
|
+
* @param {string} token
|
|
1003
|
+
* @param {number} line_number
|
|
1004
|
+
* @param {function(number, string):void} report
|
|
1005
|
+
* @returns {ParsedOperand|null}
|
|
1006
|
+
*/
|
|
1007
|
+
function parse_register_operand(token, line_number, report) {
|
|
1008
|
+
const register = /^r(\d+)(?:\.([xyzw]{1,4}))?$/i.exec(token);
|
|
1009
|
+
|
|
1010
|
+
if (register !== null) {
|
|
1011
|
+
const selectors = register[2] ?? "";
|
|
1012
|
+
const lanes = [0, 1, 2, 3].map(lane => (lane < selectors.length
|
|
1013
|
+
? SWIZZLE_LANES.indexOf(selectors.charAt(lane).toLowerCase())
|
|
1014
|
+
: lane));
|
|
1015
|
+
|
|
1016
|
+
return {
|
|
1017
|
+
kind: VM_KIND.REG,
|
|
1018
|
+
word: vm_register(Number.parseInt(register[1], 10), pack_swizzle(lanes[0], lanes[1], lanes[2], lanes[3])),
|
|
1019
|
+
selectors: selectors.length,
|
|
1020
|
+
token,
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
824
1023
|
|
|
825
|
-
|
|
1024
|
+
if (token.startsWith(PARTICLE_ASSEMBLY_IMMEDIATE_PREFIX)) {
|
|
1025
|
+
const value = parse_float(token.slice(PARTICLE_ASSEMBLY_IMMEDIATE_PREFIX.length));
|
|
1026
|
+
|
|
1027
|
+
if (value === null) {
|
|
1028
|
+
report(line_number, `Expected a literal like '${PARTICLE_ASSEMBLY_IMMEDIATE_PREFIX}1.5', got '${token}'`);
|
|
1029
|
+
return null;
|
|
826
1030
|
}
|
|
827
1031
|
|
|
1032
|
+
// The word IS the f32: what a Float32Array would hold for this value, read back as bits.
|
|
1033
|
+
return { kind: VM_KIND.IMM, word: vm_f32_bits(value) };
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
report(
|
|
1037
|
+
line_number,
|
|
1038
|
+
`Expected a register like 'r0' or 'r0.xxy', or a literal like `
|
|
1039
|
+
+ `'${PARTICLE_ASSEMBLY_IMMEDIATE_PREFIX}1.5', got '${token}'`
|
|
1040
|
+
);
|
|
1041
|
+
|
|
1042
|
+
return null;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
/**
|
|
1046
|
+
* @param {string} role a role other than the register one
|
|
1047
|
+
* @param {string} token
|
|
1048
|
+
* @param {number} line_number
|
|
1049
|
+
* @param {function(number, string):void} report
|
|
1050
|
+
* @returns {ParsedOperand|null}
|
|
1051
|
+
*/
|
|
1052
|
+
function parse_plain_operand(role, token, line_number, report) {
|
|
1053
|
+
switch (role) {
|
|
828
1054
|
case VM_OPERAND.CONST: {
|
|
829
1055
|
const index = parse_prefixed(token, "c");
|
|
830
1056
|
|
|
@@ -833,23 +1059,18 @@ function parse_operand(role, token, line_number, report) {
|
|
|
833
1059
|
return null;
|
|
834
1060
|
}
|
|
835
1061
|
|
|
836
|
-
return index;
|
|
1062
|
+
return { kind: VM_KIND.NONE, word: index };
|
|
837
1063
|
}
|
|
838
1064
|
|
|
839
1065
|
case VM_OPERAND.ATTR_OFFSET: {
|
|
840
|
-
|
|
841
|
-
report(line_number, `Expected an attribute offset like '@1', got '${token}'`);
|
|
842
|
-
return null;
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
const offset = parse_unsigned(token.slice(1));
|
|
1066
|
+
const offset = token.startsWith("@") ? parse_unsigned(token.slice(1)) : null;
|
|
846
1067
|
|
|
847
1068
|
if (offset === null) {
|
|
848
1069
|
report(line_number, `Expected an attribute offset like '@1', got '${token}'`);
|
|
849
1070
|
return null;
|
|
850
1071
|
}
|
|
851
1072
|
|
|
852
|
-
return offset;
|
|
1073
|
+
return { kind: VM_KIND.NONE, word: offset };
|
|
853
1074
|
}
|
|
854
1075
|
|
|
855
1076
|
case VM_OPERAND.COMP: {
|
|
@@ -860,11 +1081,14 @@ function parse_operand(role, token, line_number, report) {
|
|
|
860
1081
|
return null;
|
|
861
1082
|
}
|
|
862
1083
|
|
|
863
|
-
return components;
|
|
1084
|
+
return { kind: VM_KIND.NONE, word: components };
|
|
864
1085
|
}
|
|
865
1086
|
|
|
866
|
-
case VM_OPERAND.BUILTIN:
|
|
867
|
-
|
|
1087
|
+
case VM_OPERAND.BUILTIN: {
|
|
1088
|
+
const id = parse_enum_operand(token, VM_BUILTIN, "builtin", line_number, report);
|
|
1089
|
+
|
|
1090
|
+
return id === null ? null : { kind: VM_KIND.NONE, word: id };
|
|
1091
|
+
}
|
|
868
1092
|
|
|
869
1093
|
case VM_OPERAND.CURVE: {
|
|
870
1094
|
const handle = parse_prefixed(token, "k");
|
|
@@ -874,18 +1098,7 @@ function parse_operand(role, token, line_number, report) {
|
|
|
874
1098
|
return null;
|
|
875
1099
|
}
|
|
876
1100
|
|
|
877
|
-
return handle;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
case VM_OPERAND.SWIZZLE: {
|
|
881
|
-
const packed = parse_swizzle(token);
|
|
882
|
-
|
|
883
|
-
if (packed === null) {
|
|
884
|
-
report(line_number, `Expected a swizzle like '.xyzw', got '${token}'`);
|
|
885
|
-
return null;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
return packed;
|
|
1101
|
+
return { kind: VM_KIND.NONE, word: handle };
|
|
889
1102
|
}
|
|
890
1103
|
|
|
891
1104
|
default:
|
|
@@ -924,10 +1137,12 @@ function parse_enum_operand(token, enumeration, label, line_number, report) {
|
|
|
924
1137
|
}
|
|
925
1138
|
|
|
926
1139
|
/**
|
|
1140
|
+
* A legacy `SWIZZLE` pattern: exactly four selectors behind a dot.
|
|
1141
|
+
*
|
|
927
1142
|
* @param {string} token
|
|
928
|
-
* @returns {number|null} the packed
|
|
1143
|
+
* @returns {number|null} the packed pattern
|
|
929
1144
|
*/
|
|
930
|
-
function
|
|
1145
|
+
function parse_swizzle_pattern(token) {
|
|
931
1146
|
if (token.length !== 5 || !token.startsWith(".")) {
|
|
932
1147
|
return null;
|
|
933
1148
|
}
|