@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.
Files changed (410) hide show
  1. package/editor/particles/effect/ParticleEffectDocument.d.ts +21 -6
  2. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  3. package/editor/particles/effect/ParticleEffectDocument.js +38 -17
  4. package/editor/view/node-graph/NodeGraphClipboard.d.ts +186 -0
  5. package/editor/view/node-graph/NodeGraphClipboard.d.ts.map +1 -0
  6. package/editor/view/node-graph/NodeGraphClipboard.js +231 -0
  7. package/editor/view/node-graph/NodeGraphEditorView.d.ts +59 -1
  8. package/editor/view/node-graph/NodeGraphEditorView.d.ts.map +1 -1
  9. package/editor/view/node-graph/NodeGraphEditorView.js +248 -5
  10. package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
  11. package/editor/view/node-graph/NodeGraphView.js +84 -8
  12. package/editor/view/node-graph/actions/connection_bind_actions.d.ts +23 -0
  13. package/editor/view/node-graph/actions/connection_bind_actions.d.ts.map +1 -0
  14. package/editor/view/node-graph/actions/connection_bind_actions.js +39 -0
  15. package/editor/view/particles/effect/ParticleCodeEditorView.d.ts.map +1 -1
  16. package/editor/view/particles/effect/ParticleCodeEditorView.js +4 -3
  17. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts +20 -0
  18. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -0
  19. package/editor/view/particles/effect/ParticleCurveEditorView.js +574 -0
  20. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
  21. package/editor/view/particles/effect/ParticleEmitterInspectorView.js +27 -1
  22. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts +24 -0
  23. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -0
  24. package/editor/view/particles/effect/ParticleGradientEditorView.js +472 -0
  25. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts +5 -0
  26. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts.map +1 -1
  27. package/editor/view/particles/effect/ParticleGraphEditorView.js +61 -31
  28. package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
  29. package/editor/view/particles/effect/ParticleNodeParametersView.js +33 -0
  30. package/editor/view/particles/effect/particle-editor.css +123 -35
  31. package/package.json +1 -1
  32. package/src/core/binary/allocator/OffsetAllocator.d.ts +25 -16
  33. package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
  34. package/src/core/binary/allocator/OffsetAllocator.js +10 -1
  35. package/src/core/collection/array/typed/float32_array_hash.d.ts +21 -0
  36. package/src/core/collection/array/typed/float32_array_hash.d.ts.map +1 -0
  37. package/src/core/collection/array/typed/float32_array_hash.js +38 -0
  38. package/src/core/graph/csr/CSRGraph.d.ts +8 -1
  39. package/src/core/graph/csr/CSRGraph.d.ts.map +1 -1
  40. package/src/core/graph/csr/CSRGraph.js +14 -6
  41. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts +24 -0
  42. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts.map +1 -1
  43. package/src/core/model/node-graph/visual/layout/LayoutProblem.js +27 -0
  44. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +26 -0
  45. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
  46. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +28 -0
  47. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts +92 -3
  48. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts.map +1 -1
  49. package/src/core/model/node-graph/visual/layout/RouteGrid.js +405 -242
  50. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts +50 -5
  51. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts.map +1 -1
  52. package/src/core/model/node-graph/visual/layout/RouteSearch.js +160 -24
  53. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts +7 -0
  54. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts.map +1 -1
  55. package/src/core/model/node-graph/visual/layout/RouteSet.js +8 -0
  56. package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +9 -3
  57. package/src/core/model/node-graph/visual/layout/layout_build_problem.d.ts.map +1 -1
  58. package/src/core/model/node-graph/visual/layout/layout_build_problem.js +7 -0
  59. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts +9 -3
  60. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +1 -1
  61. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.js +17 -3
  62. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts +9 -6
  63. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts.map +1 -1
  64. package/src/core/model/node-graph/visual/layout/layout_node_graph.js +49 -7
  65. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts +11 -1
  66. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +1 -1
  67. package/src/core/model/node-graph/visual/layout/layout_order_layers.js +135 -16
  68. package/src/core/model/node-graph/visual/layout/route_connections.d.ts +29 -0
  69. package/src/core/model/node-graph/visual/layout/route_connections.d.ts.map +1 -1
  70. package/src/core/model/node-graph/visual/layout/route_connections.js +716 -309
  71. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts +3 -2
  72. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts.map +1 -1
  73. package/src/core/model/node-graph/visual/layout/route_grid_build.js +7 -15
  74. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts +6 -0
  75. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts.map +1 -1
  76. package/src/core/model/node-graph/visual/layout/route_nudge.js +42 -13
  77. package/src/engine/animation/AnimationUtils.js +246 -246
  78. package/src/engine/animation/Animations.js +74 -74
  79. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2078 -2078
  80. package/src/engine/ecs/EventType.d.ts +0 -1
  81. package/src/engine/ecs/EventType.js +1 -26
  82. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +1 -1
  83. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +1 -1
  84. package/src/engine/ecs/ik/ik_write_local_rotation.js +3 -7
  85. package/src/engine/ecs/parent/EntityNode.d.ts.map +1 -1
  86. package/src/engine/ecs/parent/EntityNode.js +4 -9
  87. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
  88. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +360 -364
  89. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts +41 -0
  90. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts.map +1 -0
  91. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.js +40 -0
  92. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +8 -0
  93. package/src/engine/ecs/transform/t64_announce_change.d.ts +10 -7
  94. package/src/engine/ecs/transform/t64_announce_change.d.ts.map +1 -1
  95. package/src/engine/ecs/transform/t64_announce_change.js +12 -12
  96. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts +30 -0
  97. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts.map +1 -0
  98. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js +29 -0
  99. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
  100. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +13 -21
  101. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
  102. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +4 -8
  103. package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
  104. package/src/engine/graphics3/LightSystem.js +4 -8
  105. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  106. package/src/engine/graphics3/MeshSystem.js +9 -19
  107. package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -1
  108. package/src/engine/graphics3/ParticleEmitterSystem.js +4 -8
  109. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  110. package/src/engine/graphics3/ShadedGeometrySystem.js +4 -10
  111. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts +1 -1
  112. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts.map +1 -1
  113. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +4 -8
  114. package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.js +218 -218
  115. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  116. package/src/engine/physics/ecs/PhysicsSystem.js +2 -5
  117. package/src/engine/sound/ecs/SoundListenerSystem.d.ts.map +1 -1
  118. package/src/engine/sound/ecs/SoundListenerSystem.js +6 -8
  119. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts +0 -4
  120. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts.map +1 -1
  121. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +5 -11
  122. package/src/shade/playground/particle_editor/README.md +43 -2
  123. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  124. package/src/shade/playground/particle_system/particle_prototype.js +4 -5
  125. package/src/shade/playground/particle_system/particle_scene.js +4 -4
  126. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  127. package/src/shade/renderer/Renderer.js +13 -1
  128. package/src/shade/renderer/particles/DESIGN.md +104 -19
  129. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +64 -50
  130. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  131. package/src/shade/renderer/particles/GPUParticleSystem.js +176 -78
  132. package/src/shade/renderer/particles/ParticleConstants.d.ts +59 -23
  133. package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
  134. package/src/shade/renderer/particles/ParticleConstants.js +66 -23
  135. package/src/shade/renderer/particles/ParticleRenderMode.d.ts +19 -0
  136. package/src/shade/renderer/particles/ParticleRenderMode.d.ts.map +1 -0
  137. package/src/shade/renderer/particles/ParticleRenderMode.js +33 -0
  138. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  139. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +167 -166
  140. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts +37 -0
  141. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -0
  142. package/src/shade/renderer/particles/data/particle_emitter_record.js +109 -0
  143. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +3 -3
  144. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +303 -303
  145. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +18 -0
  146. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -1
  147. package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +152 -133
  148. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +0 -11
  149. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
  150. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +720 -621
  151. package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
  152. package/src/shade/renderer/particles/graph/compile_particle_graph.js +8 -3
  153. package/src/shade/renderer/particles/graph/flatten_particle_graph.d.ts.map +1 -1
  154. package/src/shade/renderer/particles/graph/flatten_particle_graph.js +244 -213
  155. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
  156. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +6 -0
  157. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
  158. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +294 -319
  159. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.d.ts.map +1 -1
  160. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.js +524 -517
  161. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts +22 -0
  162. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts.map +1 -0
  163. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.js +517 -0
  164. package/src/shade/renderer/particles/graph/groups/simplex_reference.d.ts.map +1 -1
  165. package/src/shade/renderer/particles/graph/groups/simplex_reference.js +185 -159
  166. package/src/shade/renderer/particles/graph/make_particle_group.d.ts.map +1 -1
  167. package/src/shade/renderer/particles/graph/make_particle_group.js +2 -20
  168. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts +17 -0
  169. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts.map +1 -0
  170. package/src/shade/renderer/particles/graph/particle_compare_ops.js +22 -0
  171. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts +28 -8
  172. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts.map +1 -1
  173. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.js +49 -25
  174. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +40 -0
  175. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
  176. package/src/shade/renderer/particles/graph/particle_node_parameters.js +312 -234
  177. package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
  178. package/src/shade/renderer/particles/graph/particle_node_presentation.js +59 -3
  179. package/src/shade/renderer/particles/graph/particle_ramp.d.ts +230 -0
  180. package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -0
  181. package/src/shade/renderer/particles/graph/particle_ramp.js +403 -0
  182. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts +7 -1
  183. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts.map +1 -1
  184. package/src/shade/renderer/particles/graph/validate_particle_graph.js +66 -10
  185. package/src/shade/renderer/particles/graph_particles.d.ts +23 -69
  186. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  187. package/src/shade/renderer/particles/graph_particles.js +105 -262
  188. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  189. package/src/shade/renderer/particles/graph_particles_avboit.js +3 -2
  190. package/src/shade/renderer/particles/graph_particles_billboard.d.ts +37 -0
  191. package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +1 -0
  192. package/src/shade/renderer/particles/graph_particles_billboard.js +93 -0
  193. package/src/shade/renderer/particles/isa/InstructionStream.d.ts +51 -22
  194. package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
  195. package/src/shade/renderer/particles/isa/InstructionStream.js +98 -38
  196. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts +49 -8
  197. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts.map +1 -1
  198. package/src/shade/renderer/particles/isa/ParticleProgram.js +95 -150
  199. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +306 -64
  200. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
  201. package/src/shade/renderer/particles/isa/ParticleVMISA.js +505 -136
  202. package/src/shade/renderer/particles/isa/particle_assembly.d.ts +36 -12
  203. package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
  204. package/src/shade/renderer/particles/isa/particle_assembly.js +354 -139
  205. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts +9 -0
  206. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts.map +1 -0
  207. package/src/shade/renderer/particles/isa/validate_particle_program.js +128 -0
  208. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts +23 -0
  209. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
  210. package/src/shade/renderer/particles/layout/ParticleLayout.js +68 -0
  211. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts +77 -0
  212. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts.map +1 -0
  213. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.js +219 -0
  214. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts +83 -0
  215. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -0
  216. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +283 -0
  217. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +133 -0
  218. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts.map +1 -0
  219. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +334 -0
  220. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts +117 -0
  221. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts.map +1 -0
  222. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.js +70 -0
  223. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts +97 -0
  224. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts.map +1 -0
  225. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +462 -0
  226. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts +116 -0
  227. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts.map +1 -0
  228. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js +687 -0
  229. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts +57 -0
  230. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts.map +1 -0
  231. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +860 -0
  232. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts +115 -0
  233. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts.map +1 -0
  234. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.js +264 -0
  235. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +81 -42
  236. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
  237. package/src/shade/renderer/particles/optimizer/optimize_particle_program.js +477 -478
  238. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts +100 -0
  239. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts.map +1 -0
  240. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.js +236 -0
  241. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts +139 -59
  242. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
  243. package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +764 -647
  244. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts +40 -7
  245. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
  246. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +376 -213
  247. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts +30 -3
  248. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
  249. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +337 -223
  250. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +24 -38
  251. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
  252. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +166 -206
  253. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts +99 -0
  254. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts.map +1 -0
  255. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.js +313 -0
  256. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts +3 -2
  257. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts.map +1 -1
  258. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.js +198 -197
  259. package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.d.ts.map +1 -1
  260. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts +19 -0
  261. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
  262. package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +678 -561
  263. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts +22 -0
  264. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts.map +1 -0
  265. package/src/shade/renderer/particles/optimizer/pass_inline_constants.js +221 -0
  266. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.d.ts.map +1 -1
  267. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.js +63 -72
  268. package/src/shade/renderer/particles/optimizer/pass_pack_registers.d.ts.map +1 -1
  269. package/src/shade/renderer/particles/optimizer/pass_pack_registers.js +87 -86
  270. package/src/shade/renderer/particles/optimizer/pass_peephole.d.ts.map +1 -1
  271. package/src/shade/renderer/particles/optimizer/pass_peephole.js +392 -271
  272. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.d.ts.map +1 -1
  273. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.js +361 -268
  274. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts +4 -0
  275. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts.map +1 -0
  276. package/src/shade/renderer/particles/optimizer/pass_schedule.js +244 -0
  277. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.d.ts.map +1 -1
  278. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.js +154 -151
  279. package/src/shade/renderer/particles/particle_test_fixtures.d.ts +20 -0
  280. package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +1 -1
  281. package/src/shade/renderer/particles/particle_test_fixtures.js +229 -203
  282. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +99 -25
  283. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  284. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +438 -286
  285. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +109 -0
  286. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -0
  287. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +127 -0
  288. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +87 -102
  289. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  290. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +184 -163
  291. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts +26 -0
  292. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts.map +1 -1
  293. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts +130 -0
  294. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts.map +1 -0
  295. package/src/shade/renderer/particles/runtime/ProgramHeap.js +595 -0
  296. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts +91 -0
  297. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts.map +1 -0
  298. package/src/shade/renderer/particles/runtime/ProgramPlacement.js +106 -0
  299. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +5 -2
  300. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
  301. package/src/shade/renderer/particles/runtime/create_particle_effect.js +22 -19
  302. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts +28 -0
  303. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts.map +1 -0
  304. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.js +136 -0
  305. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts +35 -0
  306. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts.map +1 -0
  307. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.js +133 -0
  308. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts +18 -9
  309. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  310. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +20 -80
  311. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts +33 -0
  312. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -0
  313. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +114 -0
  314. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts +8 -0
  315. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  316. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +33 -101
  317. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts +45 -0
  318. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -0
  319. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +123 -0
  320. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +51 -0
  321. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +1 -0
  322. package/src/shade/renderer/particles/sort/graph_particle_sort.js +120 -0
  323. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts +6 -0
  324. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts.map +1 -0
  325. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.js +16 -0
  326. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +4 -1
  327. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  328. package/src/shade/renderer/particles/vm/ParticleVMReference.js +261 -140
  329. package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
  330. package/src/shade/renderer/particles/vm/chunk_particle_vm.js +217 -255
  331. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts +43 -0
  332. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts.map +1 -0
  333. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.js +55 -0
  334. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts +62 -0
  335. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts.map +1 -0
  336. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.js +86 -0
  337. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts +22 -0
  338. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts.map +1 -0
  339. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.js +32 -0
  340. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts +9 -0
  341. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts.map +1 -0
  342. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.js +19 -0
  343. package/src/shade/renderer/shader/chunk/noise/psrdnoise/README.md +65 -0
  344. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts +24 -0
  345. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts.map +1 -0
  346. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.js +83 -0
  347. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts +25 -0
  348. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts.map +1 -0
  349. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.js +42 -0
  350. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts +31 -0
  351. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts.map +1 -0
  352. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.js +80 -0
  353. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts +26 -0
  354. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts.map +1 -0
  355. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.js +109 -0
  356. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts +38 -0
  357. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts.map +1 -0
  358. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.js +129 -0
  359. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts +21 -0
  360. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts.map +1 -0
  361. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.js +35 -0
  362. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts +19 -0
  363. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts.map +1 -0
  364. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.js +28 -0
  365. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts +13 -0
  366. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts.map +1 -0
  367. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.js +22 -0
  368. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts +22 -0
  369. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts.map +1 -0
  370. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.js +59 -0
  371. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts +23 -0
  372. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts.map +1 -0
  373. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.js +74 -0
  374. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts +34 -1
  375. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts.map +1 -1
  376. package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +41 -1
  377. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +3 -2
  378. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  379. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +49 -10
  380. package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
  381. package/src/view/minimap/dom/MinimapCameraView.js +4 -9
  382. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts +0 -15
  383. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts.map +0 -1
  384. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts +0 -45
  385. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts.map +0 -1
  386. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts +0 -24
  387. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts.map +0 -1
  388. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts +0 -19
  389. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts.map +0 -1
  390. package/src/engine/ecs/transform/__probe.d.ts +0 -4
  391. package/src/engine/ecs/transform/__probe.d.ts.map +0 -1
  392. package/src/engine/ecs/util/hideEntityGracefully.d.ts +0 -9
  393. package/src/engine/ecs/util/hideEntityGracefully.d.ts.map +0 -1
  394. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts +0 -27
  395. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts.map +0 -1
  396. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts +0 -14
  397. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +0 -1
  398. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts +0 -156
  399. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts.map +0 -1
  400. package/src/shade/renderer/particles/runtime/Emitter.d.ts +0 -219
  401. package/src/shade/renderer/particles/runtime/Emitter.d.ts.map +0 -1
  402. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts +0 -77
  403. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts.map +0 -1
  404. package/src/shade/renderer/particles/runtime/ProgramArena.js +0 -155
  405. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts +0 -15
  406. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts.map +0 -1
  407. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts +0 -34
  408. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts.map +0 -1
  409. package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts +0 -32
  410. package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts.map +0 -1
@@ -1,5 +1,3 @@
1
- /** @param {number} seed @returns {function(): number} */
2
- export function mulberry32(seed: number): () => number;
3
1
  /**
4
2
  * A random program, in the UPDATE section.
5
3
  *
@@ -7,10 +5,39 @@ export function mulberry32(seed: number): () => number;
7
5
  * @param {object} [options]
8
6
  * @param {number} [options.body_length] instructions in the body, before the closing stores
9
7
  * @param {boolean} [options.halt] place a `HALT` part-way through, so unreachable code exists
8
+ * @param {boolean} [options.tagged] whether sources may be literals
9
+ * @param {number} [options.register_slots] slots to carve into values — the FAST interpreter's file
10
+ * by default, not the ISA's 256. What is being fuzzed is the optimizer over programs of the shape
11
+ * a real effect has, and carving every addressable slot would make every generated program a
12
+ * register-pressure outlier instead.
10
13
  * @returns {ParticleProgram}
11
14
  */
12
- export function random_particle_program(rand: () => number, { body_length, halt }?: {
15
+ export function random_particle_program(rand: () => number, { body_length, halt, tagged, register_slots, }?: {
13
16
  body_length?: number;
14
17
  halt?: boolean;
18
+ tagged?: boolean;
19
+ register_slots?: number;
20
+ }): ParticleProgram;
21
+ /**
22
+ * A program built out of the shape the copy rewrites exist for: a run of lanes taken out of one
23
+ * value and put into another a lane at a time, spelled as plain copies or as lane-picking swizzles.
24
+ *
25
+ * {@link random_particle_program} cannot reach it. Its operands come from one width class, so two of
26
+ * its copies never land on ADJACENT runs, which is the whole of what a merge is about. So the shape
27
+ * the node library produces from every `decompose` and every `vec2..4` has to be generated on
28
+ * purpose, with the things that must STOP a merge mixed in at the same time: a write to a slot the
29
+ * rest of the run still reads, a read of one it is about to fill, a draw, a `HALT`.
30
+ *
31
+ * Operands are drawn freely: the destination may land on top of the source, which the executors
32
+ * define — every source is read before the destination is written — and the rewrites have to
33
+ * respect.
34
+ *
35
+ * @param {function(): number} rand
36
+ * @param {object} [options]
37
+ * @param {number} [options.groups] how many take-apart-and-rebuild runs to write
38
+ * @returns {ParticleProgram}
39
+ */
40
+ export function random_particle_copy_program(rand: () => number, { groups }?: {
41
+ groups?: number;
15
42
  }): ParticleProgram;
16
43
  //# sourceMappingURL=particle_program_fuzz.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"particle_program_fuzz.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/particle_program_fuzz.js"],"names":[],"mappings":"AAoCA,yDAAyD;AACzD,iCADY,MAAM,SAA6B,MAAM,CAWpD;AAED;;;;;;;;GAQG;AACH,oDANuB,MAAM;IAED,WAAW,GAA5B,MAAM;IACY,IAAI,GAAtB,OAAO;oBAoFjB"}
1
+ {"version":3,"file":"particle_program_fuzz.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/particle_program_fuzz.js"],"names":[],"mappings":"AAkDA;;;;;;;;;;;;;GAaG;AACH,oDAXuB,MAAM;IAED,WAAW,GAA5B,MAAM;IACY,IAAI,GAAtB,OAAO;IACW,MAAM,GAAxB,OAAO;IACU,cAAc,GAA/B,MAAM;oBAqHhB;AA8ED;;;;;;;;;;;;;;;;;;GAkBG;AACH,yDALuB,MAAM;IAED,MAAM,GAAvB,MAAM;oBAmEhB"}
@@ -1,223 +1,337 @@
1
- import { PARTICLE_RECORD_WORD_COUNT, PARTICLE_VM_REGISTER_SLOTS } from "../ParticleConstants.js";
2
- import { ParticleAssembler } from "../isa/ParticleAssembler.js";
3
- import { VM_BUILTIN, VM_ISA, VM_OP, VM_OPERAND, pack_swizzle } from "../isa/ParticleVMISA.js";
4
-
5
- /**
6
- * Random but well-formed particle programs, for holding the optimizer to
7
- * {@link ./particle_program_equivalence.js}'s bit-identity property on programs nobody wrote.
8
- *
9
- * The generator carves the register file into value runs of random width and draws every operand of
10
- * an instruction from one width class, which is what makes the results legal: the ISA lets two
11
- * operands of an instruction name the same run or disjoint ones, never a partial overlap, and runs
12
- * of equal width either coincide or do not touch. `../vm/chunk_particle_vm.spec.js` fuzzes the two
13
- * executors against each other the same way; the difference here is that nothing is excluded for
14
- * being numerically awkward. Division by zero, `sqrt` of a negative and `log` of zero are all fair
15
- * game, because both sides of this comparison are the same executor and an optimizer that turns
16
- * `NaN` into a number is exactly what wants catching.
17
- *
18
- * The mix is deliberately biased towards what the optimizer has opinions about: constants that are
19
- * 0 and 1, `SELECT`s whose condition is one of them, copies, broadcasts, and results that nothing
20
- * ever stores.
21
- */
22
-
23
- /** Every opcode a generated program may contain, `HALT` aside — that one is placed by hand. */
24
- const FUZZ_OPS = [
25
- VM_OP.MOV, VM_OP.ADD, VM_OP.SUB, VM_OP.MUL, VM_OP.DIV, VM_OP.MAD, VM_OP.MIN, VM_OP.MAX,
26
- VM_OP.MIX, VM_OP.CLAMP, VM_OP.SCALE, VM_OP.NEG, VM_OP.ABS, VM_OP.FLOOR, VM_OP.FRACT,
27
- VM_OP.SQRT, VM_OP.SIN, VM_OP.COS, VM_OP.EXP, VM_OP.LOG, VM_OP.POW, VM_OP.STEP,
28
- VM_OP.SMOOTHSTEP, VM_OP.DOT, VM_OP.CROSS, VM_OP.LENGTH, VM_OP.NORMALIZE, VM_OP.DISTANCE,
29
- VM_OP.SWIZZLE, VM_OP.CMP_LT, VM_OP.CMP_LE, VM_OP.CMP_GT, VM_OP.CMP_GE, VM_OP.CMP_EQ,
30
- VM_OP.SELECT, VM_OP.RANDOM, VM_OP.CURVE, VM_OP.LOAD_CONST, VM_OP.LOAD_ATTR, VM_OP.LOAD_BUILTIN,
31
- VM_OP.NOP,
32
- ];
33
-
34
- /** Values the folding pass has rules about, mixed in with arbitrary ones. */
35
- const NOTABLE_CONSTANTS = [0, 1, -1, 0.5, 2, -0];
36
-
37
- /** @param {number} seed @returns {function(): number} */
38
- export function mulberry32(seed) {
39
- let a = seed >>> 0;
40
-
41
- return function () {
42
- a |= 0;
43
- a = (a + 0x6D2B79F5) | 0;
44
- let t = Math.imul(a ^ (a >>> 15), 1 | a);
45
- t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
46
- return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
47
- };
48
- }
49
-
50
- /**
51
- * A random program, in the UPDATE section.
52
- *
53
- * @param {function(): number} rand
54
- * @param {object} [options]
55
- * @param {number} [options.body_length] instructions in the body, before the closing stores
56
- * @param {boolean} [options.halt] place a `HALT` part-way through, so unreachable code exists
57
- * @returns {ParticleProgram}
58
- */
59
- export function random_particle_program(rand, { body_length = 24, halt = false } = {}) {
60
- const assembler = new ParticleAssembler();
61
- const stream = assembler.update;
62
-
63
- /** @type {Array<{base: number, width: number}>} the file, carved into runs */
64
- const values = [];
65
-
66
- for (let base = 0; base < PARTICLE_VM_REGISTER_SLOTS;) {
67
- const width = 1 + Math.floor(rand() * 4);
68
-
69
- if (base + width > PARTICLE_VM_REGISTER_SLOTS) {
70
- break;
71
- }
72
-
73
- values.push({ base, width });
74
- base += width;
75
- }
76
-
77
- /** @type {Map<number, Array<{base: number, width: number}>>} */
78
- const by_width = new Map();
79
-
80
- for (const value of values) {
81
- if (!by_width.has(value.width)) {
82
- by_width.set(value.width, []);
83
- }
84
-
85
- by_width.get(value.width).push(value);
86
- }
87
-
88
- const widths = Array.from(by_width.keys());
89
- const pick = (list) => list[Math.floor(rand() * list.length)];
90
- const constant = () => (rand() < 0.45
91
- ? NOTABLE_CONSTANTS[Math.floor(rand() * NOTABLE_CONSTANTS.length)]
92
- : Math.round((rand() * 8 - 4) * 64) / 64);
93
-
94
- // Seed the file, so a read is a read of something rather than of the zeroed file.
95
- for (const value of values) {
96
- stream.loadConst(
97
- value.base,
98
- assembler.constant(constant(), constant(), constant(), constant()),
99
- value.width
100
- );
101
- }
102
-
103
- for (let i = 0; i < body_length; i++) {
104
- emit_random_instruction(stream, assembler, rand, { values, by_width, widths, pick, constant });
105
- }
106
-
107
- // Store what the file holds, so the fuzzed results are actually observed rather than dropped by
108
- // the very dead-code pass under test.
109
- let cursor = 1;
110
-
111
- for (const value of values) {
112
- if (cursor + value.width > PARTICLE_RECORD_WORD_COUNT) {
113
- break;
114
- }
115
-
116
- stream.storeAttr(value.base, cursor, value.width);
117
- cursor += value.width;
118
- }
119
-
120
- if (rand() < 0.35) {
121
- stream.kill(pick(values).base);
122
- }
123
-
124
- // A tail behind a `HALT`: more instructions, more draws and another store, none of which run.
125
- // Anything the optimizer keeps here it has kept for nothing; anything it lets influence the
126
- // program above is a bug the equivalence check will name.
127
- if (halt) {
128
- stream.halt();
129
-
130
- for (let i = 0; i < 4; i++) {
131
- emit_random_instruction(stream, assembler, rand, { values, by_width, widths, pick, constant });
132
- }
133
-
134
- const unreachable = pick(values);
135
-
136
- stream.storeAttr(unreachable.base, 1, unreachable.width);
137
- }
138
-
139
- return assembler.build();
140
- }
141
-
142
- /**
143
- * One instruction, with operands drawn from a single width class so the operand runs coincide or
144
- * stay disjoint.
145
- *
146
- * @param {import("../isa/InstructionStream.js").InstructionStream} stream
147
- * @param {ParticleAssembler} assembler
148
- * @param {function(): number} rand
149
- * @param {object} pool
150
- */
151
- function emit_random_instruction(stream, assembler, rand, pool) {
152
- const { by_width, widths, pick, constant } = pool;
153
- const op = FUZZ_OPS[Math.floor(rand() * FUZZ_OPS.length)];
154
- const meta = VM_ISA.get(op);
155
- const candidates = widths.filter(w => w >= meta.min_width);
156
-
157
- if (candidates.length === 0) {
158
- return;
159
- }
160
-
161
- const width = pick(candidates);
162
- const group = by_width.get(width);
163
- const destination = pick(group);
164
- const dst = destination.base;
165
-
166
- switch (op) {
167
- case VM_OP.NOP:
168
- stream.emit(VM_OP.NOP);
169
- return;
170
-
171
- case VM_OP.RANDOM:
172
- stream.random(dst, width);
173
- return;
174
-
175
- case VM_OP.LOAD_CONST:
176
- stream.loadConst(dst, assembler.constant(constant(), constant(), constant(), constant()), width);
177
- return;
178
-
179
- case VM_OP.LOAD_BUILTIN:
180
- stream.loadBuiltin(dst, Math.floor(rand() * Object.keys(VM_BUILTIN).length), width);
181
- return;
182
-
183
- case VM_OP.LOAD_ATTR: {
184
- const components = 1 + Math.floor(rand() * 4);
185
- const offset = 1 + Math.floor(rand() * (PARTICLE_RECORD_WORD_COUNT - components - 1));
186
-
187
- stream.loadAttr(dst, offset, components, width);
188
- return;
189
- }
190
-
191
- case VM_OP.CURVE:
192
- stream.curve(dst, Math.floor(rand() * 4), pick(group).base, width);
193
- return;
194
-
195
- case VM_OP.SWIZZLE: {
196
- const source = pick(group);
197
- const lane = () => Math.floor(rand() * source.width);
198
-
199
- stream.emit(op, dst, source.base, pack_swizzle(lane(), lane(), lane(), lane()), 0, width);
200
- return;
201
- }
202
-
203
- default: {
204
- // A `SELECT` whose condition is a constant is the shape the folding pass exists for, and
205
- // random registers hold one about never — so it is worth steering into deliberately.
206
- if (op === VM_OP.SELECT && rand() < 0.4) {
207
- const condition = pick(group).base;
208
-
209
- stream.loadConst(
210
- condition,
211
- assembler.constant(...Array.from({ length: 4 }, () => (rand() < 0.5 ? 0 : 1))),
212
- width
213
- );
214
- stream.emit(op, dst, pick(group).base, pick(group).base, condition, width);
215
- return;
216
- }
217
-
218
- const operand = (slot) => (meta.operands[slot] === VM_OPERAND.REG ? pick(group).base : 0);
219
-
220
- stream.emit(op, dst, operand(0), operand(1), operand(2), width);
221
- }
222
- }
223
- }
1
+ import { PARTICLE_RECORD_WORD_COUNT, PARTICLE_VM_FAST_REGISTER_SLOTS } from "../ParticleConstants.js";
2
+ import { ParticleAssembler } from "../isa/ParticleAssembler.js";
3
+ import {
4
+ VM_BUILTIN,
5
+ VM_ISA,
6
+ VM_MAX_WIDTH,
7
+ VM_OP,
8
+ VM_OPERAND,
9
+ pack_swizzle,
10
+ vm_immediate,
11
+ vm_register,
12
+ } from "../isa/ParticleVMISA.js";
13
+
14
+ /**
15
+ * Random but well-formed particle programs, for holding the optimizer to
16
+ * {@link ./particle_program_equivalence.js}'s bit-identity property on programs nobody wrote.
17
+ *
18
+ * The generator carves the register file into value runs of random width and draws every operand of
19
+ * an instruction from one width class, so a source is a whole value: the same shape the node
20
+ * compiler produces, and the one the passes have opinions about. `../vm/chunk_particle_vm.spec.js`
21
+ * fuzzes the two executors against each other the same way; the difference here is that nothing is
22
+ * excluded for being numerically awkward. Division by zero, `sqrt` of a negative and `log` of zero
23
+ * are all fair game, because both sides of this comparison are the same executor and an optimizer
24
+ * that turns `NaN` into a number is exactly what wants catching.
25
+ *
26
+ * The mix is deliberately biased towards what the optimizer has opinions about: constants that are
27
+ * 0 and 1, `SELECT`s whose condition is one of them, copies, broadcasts, and results that nothing
28
+ * ever stores.
29
+ *
30
+ * With `tagged`, a source is sometimes a literal rather than a register — the operand kinds of
31
+ * {@link ../isa/ParticleVMISA.js} — so every pass meets literals in every slot of every opcode, in
32
+ * programs that also carry the shapes it rewrites. Register sources are sometimes read through a
33
+ * swizzle in either mode, since a swizzle is part of what a register operand is.
34
+ */
35
+
36
+ /** Every opcode a generated program may contain, `HALT` aside — that one is placed by hand. */
37
+ const FUZZ_OPS = [
38
+ VM_OP.MOV, VM_OP.ADD, VM_OP.SUB, VM_OP.MUL, VM_OP.DIV, VM_OP.MAD, VM_OP.MIN, VM_OP.MAX,
39
+ VM_OP.MIX, VM_OP.CLAMP, VM_OP.NEG, VM_OP.ABS, VM_OP.FLOOR, VM_OP.FRACT,
40
+ VM_OP.SQRT, VM_OP.SIN, VM_OP.COS, VM_OP.EXP, VM_OP.LOG, VM_OP.POW, VM_OP.STEP,
41
+ VM_OP.SMOOTHSTEP, VM_OP.RSQRT, VM_OP.TAN, VM_OP.ASIN, VM_OP.ACOS, VM_OP.ATAN2,
42
+ VM_OP.DOT, VM_OP.CROSS, VM_OP.LENGTH, VM_OP.NORMALIZE, VM_OP.DISTANCE,
43
+ VM_OP.CMP_LT, VM_OP.CMP_LE, VM_OP.CMP_GT, VM_OP.CMP_GE, VM_OP.CMP_EQ,
44
+ VM_OP.SELECT, VM_OP.RANDOM, VM_OP.CURVE, VM_OP.LOAD_CONST, VM_OP.LOAD_ATTR, VM_OP.LOAD_BUILTIN,
45
+ VM_OP.NOP,
46
+ ];
47
+
48
+ /** Values the folding pass has rules about, mixed in with arbitrary ones. */
49
+ const NOTABLE_CONSTANTS = [0, 1, -1, 0.5, 2, -0];
50
+
51
+ /**
52
+ * A random program, in the UPDATE section.
53
+ *
54
+ * @param {function(): number} rand
55
+ * @param {object} [options]
56
+ * @param {number} [options.body_length] instructions in the body, before the closing stores
57
+ * @param {boolean} [options.halt] place a `HALT` part-way through, so unreachable code exists
58
+ * @param {boolean} [options.tagged] whether sources may be literals
59
+ * @param {number} [options.register_slots] slots to carve into values — the FAST interpreter's file
60
+ * by default, not the ISA's 256. What is being fuzzed is the optimizer over programs of the shape
61
+ * a real effect has, and carving every addressable slot would make every generated program a
62
+ * register-pressure outlier instead.
63
+ * @returns {ParticleProgram}
64
+ */
65
+ export function random_particle_program(rand, {
66
+ body_length = 24,
67
+ halt = false,
68
+ tagged = false,
69
+ register_slots = PARTICLE_VM_FAST_REGISTER_SLOTS,
70
+ } = {}) {
71
+ const assembler = new ParticleAssembler();
72
+ const stream = assembler.update;
73
+
74
+ /** @type {Array<{base: number, width: number}>} the file, carved into runs */
75
+ const values = [];
76
+
77
+ for (let base = 0; base < register_slots;) {
78
+ const width = 1 + Math.floor(rand() * 4);
79
+
80
+ if (base + width > register_slots) {
81
+ break;
82
+ }
83
+
84
+ values.push({ base, width });
85
+ base += width;
86
+ }
87
+
88
+ /** @type {Map<number, Array<{base: number, width: number}>>} */
89
+ const by_width = new Map();
90
+
91
+ for (const value of values) {
92
+ if (!by_width.has(value.width)) {
93
+ by_width.set(value.width, []);
94
+ }
95
+
96
+ by_width.get(value.width).push(value);
97
+ }
98
+
99
+ const widths = Array.from(by_width.keys());
100
+ const pick = (list) => list[Math.floor(rand() * list.length)];
101
+ const constant = () => (rand() < 0.45
102
+ ? NOTABLE_CONSTANTS[Math.floor(rand() * NOTABLE_CONSTANTS.length)]
103
+ : Math.round((rand() * 8 - 4) * 64) / 64);
104
+
105
+ /**
106
+ * A source in a register slot: a value of the width class, sometimes read through a swizzle
107
+ * over its own lanes, or — when tagging — a literal.
108
+ *
109
+ * @param {Array<{base: number, width: number}>} group
110
+ * @returns {number|{kind: number, word: number}}
111
+ */
112
+ const source = (group) => {
113
+ if (tagged && rand() < 0.2) {
114
+ return vm_immediate(constant());
115
+ }
116
+
117
+ const value = pick(group);
118
+
119
+ if (rand() < 0.15) {
120
+ const lane = () => Math.floor(rand() * value.width);
121
+
122
+ return vm_register(value.base, pack_swizzle(lane(), lane(), lane(), lane()));
123
+ }
124
+
125
+ return value.base;
126
+ };
127
+
128
+ // Seed the file, so a read is a read of something rather than of the zeroed file.
129
+ for (const value of values) {
130
+ stream.loadConst(
131
+ value.base,
132
+ assembler.constant(constant(), constant(), constant(), constant()),
133
+ value.width
134
+ );
135
+ }
136
+
137
+ const pool = { values, by_width, widths, pick, constant, source };
138
+
139
+ for (let i = 0; i < body_length; i++) {
140
+ emit_random_instruction(stream, assembler, rand, pool);
141
+ }
142
+
143
+ // Store what the file holds, so the fuzzed results are actually observed rather than dropped by
144
+ // the very dead-code pass under test.
145
+ let cursor = 1;
146
+
147
+ for (const value of values) {
148
+ if (cursor + value.width > PARTICLE_RECORD_WORD_COUNT) {
149
+ break;
150
+ }
151
+
152
+ stream.storeAttr(value.base, cursor, value.width);
153
+ cursor += value.width;
154
+ }
155
+
156
+ if (rand() < 0.35) {
157
+ stream.kill(pick(values).base);
158
+ }
159
+
160
+ // A tail behind a `HALT`: more instructions, more draws and another store, none of which run.
161
+ // Anything the optimizer keeps here it has kept for nothing; anything it lets influence the
162
+ // program above is a bug the equivalence check will name.
163
+ if (halt) {
164
+ stream.halt();
165
+
166
+ for (let i = 0; i < 4; i++) {
167
+ emit_random_instruction(stream, assembler, rand, pool);
168
+ }
169
+
170
+ const unreachable = pick(values);
171
+
172
+ stream.storeAttr(unreachable.base, 1, unreachable.width);
173
+ }
174
+
175
+ return assembler.build();
176
+ }
177
+
178
+ /**
179
+ * One instruction, with operands drawn from a single width class so every source is a whole value.
180
+ *
181
+ * @param {import("../isa/InstructionStream.js").InstructionStream} stream
182
+ * @param {ParticleAssembler} assembler
183
+ * @param {function(): number} rand
184
+ * @param {object} pool
185
+ */
186
+ function emit_random_instruction(stream, assembler, rand, pool) {
187
+ const { by_width, widths, pick, constant, source } = pool;
188
+ const op = FUZZ_OPS[Math.floor(rand() * FUZZ_OPS.length)];
189
+ const meta = VM_ISA.get(op);
190
+ const candidates = widths.filter(w => w >= meta.min_width);
191
+
192
+ if (candidates.length === 0) {
193
+ return;
194
+ }
195
+
196
+ const width = pick(candidates);
197
+ const group = by_width.get(width);
198
+ const dst = pick(group).base;
199
+
200
+ switch (op) {
201
+ case VM_OP.NOP:
202
+ stream.emit(VM_OP.NOP);
203
+ return;
204
+
205
+ case VM_OP.RANDOM:
206
+ stream.random(dst, width);
207
+ return;
208
+
209
+ case VM_OP.LOAD_CONST:
210
+ stream.loadConst(dst, assembler.constant(constant(), constant(), constant(), constant()), width);
211
+ return;
212
+
213
+ case VM_OP.LOAD_BUILTIN:
214
+ stream.loadBuiltin(dst, Math.floor(rand() * Object.keys(VM_BUILTIN).length), width);
215
+ return;
216
+
217
+ case VM_OP.LOAD_ATTR: {
218
+ const components = 1 + Math.floor(rand() * 4);
219
+ const offset = 1 + Math.floor(rand() * (PARTICLE_RECORD_WORD_COUNT - components - 1));
220
+
221
+ stream.loadAttr(dst, offset, components, width);
222
+ return;
223
+ }
224
+
225
+ case VM_OP.CURVE: {
226
+ const handle = Math.floor(rand() * 4);
227
+
228
+ stream.curve(dst, handle, source(group), width);
229
+ return;
230
+ }
231
+
232
+ default: {
233
+ // A `SELECT` whose condition is a constant is the shape the folding pass exists for, and
234
+ // random registers hold one about never — so it is worth steering into deliberately.
235
+ if (op === VM_OP.SELECT && rand() < 0.4) {
236
+ const condition = pick(group).base;
237
+
238
+ stream.loadConst(
239
+ condition,
240
+ assembler.constant(...Array.from({ length: 4 }, () => (rand() < 0.5 ? 0 : 1))),
241
+ width
242
+ );
243
+ stream.emit(op, dst, source(group), source(group), condition, width);
244
+ return;
245
+ }
246
+
247
+ const operand = (slot) => (meta.operands[slot] === VM_OPERAND.REG ? source(group) : 0);
248
+
249
+ stream.emit(op, dst, operand(0), operand(1), operand(2), width);
250
+ }
251
+ }
252
+ }
253
+
254
+ /**
255
+ * A program built out of the shape the copy rewrites exist for: a run of lanes taken out of one
256
+ * value and put into another a lane at a time, spelled as plain copies or as lane-picking swizzles.
257
+ *
258
+ * {@link random_particle_program} cannot reach it. Its operands come from one width class, so two of
259
+ * its copies never land on ADJACENT runs, which is the whole of what a merge is about. So the shape
260
+ * the node library produces from every `decompose` and every `vec2..4` has to be generated on
261
+ * purpose, with the things that must STOP a merge mixed in at the same time: a write to a slot the
262
+ * rest of the run still reads, a read of one it is about to fill, a draw, a `HALT`.
263
+ *
264
+ * Operands are drawn freely: the destination may land on top of the source, which the executors
265
+ * define — every source is read before the destination is written — and the rewrites have to
266
+ * respect.
267
+ *
268
+ * @param {function(): number} rand
269
+ * @param {object} [options]
270
+ * @param {number} [options.groups] how many take-apart-and-rebuild runs to write
271
+ * @returns {ParticleProgram}
272
+ */
273
+ export function random_particle_copy_program(rand, { groups = 5 } = {}) {
274
+ const assembler = new ParticleAssembler();
275
+ const stream = assembler.update;
276
+ const pick = (n) => Math.floor(rand() * n);
277
+
278
+ /** Enough of the file for the runs to be placed at random inside it, and no more. */
279
+ const slots = 20;
280
+
281
+ // Seed the file, so a copy copies something.
282
+ for (let base = 0; base < slots; base += VM_MAX_WIDTH) {
283
+ stream.loadConst(
284
+ base,
285
+ assembler.constant(...Array.from({ length: VM_MAX_WIDTH }, () => Math.round((rand() * 8 - 4) * 64) / 64)),
286
+ VM_MAX_WIDTH
287
+ );
288
+ }
289
+
290
+ for (let group = 0; group < groups; group++) {
291
+ const source = pick(slots - VM_MAX_WIDTH);
292
+ const destination = pick(slots - VM_MAX_WIDTH);
293
+ const as_swizzle = rand() < 0.5;
294
+ const lanes = Array.from({ length: 2 + pick(3) }, (_, lane) => lane);
295
+
296
+ // Out of order sometimes, and sometimes with a lane missing: a merge must not care about the
297
+ // first and must not happen for the second.
298
+ if (rand() < 0.25) {
299
+ lanes.reverse();
300
+ }
301
+
302
+ if (rand() < 0.2) {
303
+ lanes.splice(pick(lanes.length), 1);
304
+ }
305
+
306
+ for (const lane of lanes) {
307
+ if (as_swizzle) {
308
+ stream.mov(destination + lane, vm_register(source, pack_swizzle(lane, lane, lane, lane)), 1);
309
+ } else {
310
+ stream.mov(destination + lane, source + lane, 1);
311
+ }
312
+
313
+ const roll = rand();
314
+
315
+ if (roll < 0.12) {
316
+ stream.loadConst(source + pick(VM_MAX_WIDTH), assembler.constant(rand()), 1);
317
+ } else if (roll < 0.24) {
318
+ stream.storeAttr(destination + pick(VM_MAX_WIDTH), 1 + pick(8), 1);
319
+ } else if (roll < 0.32) {
320
+ stream.emit(VM_OP.ADD, pick(slots), pick(slots), pick(slots), 0, 1);
321
+ } else if (roll < 0.36) {
322
+ stream.random(pick(slots), 1);
323
+ }
324
+ }
325
+
326
+ if (rand() < 0.08) {
327
+ stream.halt();
328
+ }
329
+ }
330
+
331
+ // Store the file, so what the copies moved is observed rather than dropped as dead.
332
+ for (let base = 0; base + VM_MAX_WIDTH <= slots && base + VM_MAX_WIDTH < PARTICLE_RECORD_WORD_COUNT; base += VM_MAX_WIDTH) {
333
+ stream.storeAttr(base, base + 1, VM_MAX_WIDTH);
334
+ }
335
+
336
+ return assembler.build();
337
+ }