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