@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,244 @@
1
+ import { decode_particle_instructions, particle_peak_live_slots, particle_read_slots } from "./particle_program_analysis.js";
2
+
3
+ /** @type {string} */
4
+ export const PARTICLE_PASS_SCHEDULE = "schedule";
5
+
6
+ /**
7
+ * Reorder the instructions so that fewer values are alive at once.
8
+ *
9
+ * A frontend lowers in whatever order it visits, and the node compiler's order is the graph's: a
10
+ * constant is loaded where the graph mentions it and a corner offset is computed alongside the
11
+ * others, both a long way above their one consumer. Every instruction in between then carries that
12
+ * value in the file. The register allocator can only reuse slots whose values have died, so a
13
+ * value that lives longer than it needs to is a slot the allocator cannot give back — the
14
+ * curl-noise effect held a vec4 across seventy instructions this way.
15
+ *
16
+ * ## What may be reordered
17
+ *
18
+ * Straight-line code has three hazards per slot — a read must follow the write it reads, a write
19
+ * must follow the reads of the value it replaces, and two writes keep their order — and the
20
+ * schedule keeps every one of them, so the sequence of writes and reads of each slot is the one the
21
+ * program had. Instructions with side effects are barriers: nothing crosses a draw, a store, a kill
22
+ * or a halt in either direction, and they keep their order among themselves. That is stricter than
23
+ * a pure instruction crossing a store needs, and it is what keeps the ordering promises of
24
+ * `optimize_particle_program.js` — the draw sequence, attribute aliasing — structural for this pass
25
+ * as for every other.
26
+ *
27
+ * ## How the order is chosen
28
+ *
29
+ * Backwards, one instruction at a time, from the set whose consumers are all already placed: the
30
+ * one whose placement leaves the fewest slots alive above it, which is the one that frees the most
31
+ * of what it writes against what it reads. Ties go to the instruction that came last in the program
32
+ * as it was, so an order that is already as good as this greedy can make it comes back unchanged —
33
+ * and the schedule is kept only when its peak is strictly lower than the program's, so the pass is
34
+ * a fixed point of itself and never makes a program worse by the one measure it is for.
35
+ *
36
+ * It is a greedy, and a greedy can be fooled; the differential harness holds it to bit-identity
37
+ * whatever order it picks, and the peak is measured rather than assumed.
38
+ *
39
+ * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
40
+ */
41
+ export function pass_schedule(instructions, context) {
42
+ const decoded = decode_particle_instructions(instructions);
43
+ const slots = context.register_slots;
44
+ const order = schedule(decoded, slots);
45
+
46
+ if (order === null) {
47
+ return null;
48
+ }
49
+
50
+ const scheduled = order.map(index => decoded[index]);
51
+
52
+ if (particle_peak_live_slots(scheduled, slots) >= particle_peak_live_slots(decoded, slots)) {
53
+ return null;
54
+ }
55
+
56
+ return order.map(index => instructions[index]);
57
+ }
58
+
59
+ /**
60
+ * @param {import("./particle_program_analysis.js").ParticleDecodedInstruction[]} decoded
61
+ * @param {number} slots size of the register file
62
+ * @returns {number[]|null} instruction indices in their new order, or `null` when an operand
63
+ * reaches outside the file
64
+ */
65
+ function schedule(decoded, slots) {
66
+ const count = decoded.length;
67
+ const predecessors = build_dependencies(decoded, slots);
68
+
69
+ if (predecessors === null) {
70
+ return null;
71
+ }
72
+
73
+ /** @type {Int32Array} per instruction, how many of its dependents are still unplaced */
74
+ const pending = new Int32Array(count);
75
+
76
+ for (let i = 0; i < count; i++) {
77
+ for (const predecessor of predecessors[i]) {
78
+ pending[predecessor]++;
79
+ }
80
+ }
81
+
82
+ /** @type {Set<number>} instructions whose dependents are all placed */
83
+ const ready = new Set();
84
+
85
+ for (let i = 0; i < count; i++) {
86
+ if (pending[i] === 0) {
87
+ ready.add(i);
88
+ }
89
+ }
90
+
91
+ /** @type {Uint8Array} slots alive just above the instructions placed so far */
92
+ const live = new Uint8Array(slots);
93
+ /** @type {Uint8Array} scratch for scoring a candidate */
94
+ const trial = new Uint8Array(slots);
95
+ /** @type {number[]} placed instructions, last first */
96
+ const reversed = [];
97
+
98
+ while (reversed.length < count) {
99
+ let best = -1;
100
+ let best_live = Infinity;
101
+
102
+ for (const candidate of ready) {
103
+ const alive = live_above(decoded[candidate], live, trial);
104
+
105
+ if (alive < best_live || (alive === best_live && candidate > best)) {
106
+ best = candidate;
107
+ best_live = alive;
108
+ }
109
+ }
110
+
111
+ live_above(decoded[best], live, trial);
112
+ live.set(trial);
113
+ reversed.push(best);
114
+ ready.delete(best);
115
+
116
+ for (const predecessor of predecessors[best]) {
117
+ if (--pending[predecessor] === 0) {
118
+ ready.add(predecessor);
119
+ }
120
+ }
121
+ }
122
+
123
+ return reversed.reverse();
124
+ }
125
+
126
+ /**
127
+ * The slots alive just above an instruction, given those alive just below it: what it reads, plus
128
+ * whatever was alive that it does not write.
129
+ *
130
+ * @param {import("./particle_program_analysis.js").ParticleDecodedInstruction} instruction
131
+ * @param {Uint8Array} below
132
+ * @param {Uint8Array} above written here
133
+ * @returns {number} how many
134
+ */
135
+ function live_above(instruction, below, above) {
136
+ above.set(below);
137
+
138
+ if (instruction.write !== null) {
139
+ for (let lane = 0; lane < instruction.write.span; lane++) {
140
+ above[instruction.write.base + lane] = 0;
141
+ }
142
+ }
143
+
144
+ for (const read of instruction.reads) {
145
+ for (const slot of particle_read_slots(read)) {
146
+ above[slot] = 1;
147
+ }
148
+ }
149
+
150
+ let alive = 0;
151
+
152
+ for (let slot = 0; slot < above.length; slot++) {
153
+ alive += above[slot];
154
+ }
155
+
156
+ return alive;
157
+ }
158
+
159
+ /**
160
+ * Per instruction, the instructions it must come after.
161
+ *
162
+ * @param {import("./particle_program_analysis.js").ParticleDecodedInstruction[]} decoded
163
+ * @param {number} slots
164
+ * @returns {Set<number>[]|null} `null` when an operand reaches outside the file
165
+ */
166
+ function build_dependencies(decoded, slots) {
167
+ const predecessors = decoded.map(() => new Set());
168
+ /** @type {Int32Array} per slot, the last instruction to write it */
169
+ const writer = new Int32Array(slots).fill(-1);
170
+ /** @type {number[][]} per slot, the instructions that read its current value */
171
+ const readers = Array.from({ length: slots }, () => []);
172
+
173
+ let barrier = -1;
174
+
175
+ for (let i = 0; i < decoded.length; i++) {
176
+ const instruction = decoded[i];
177
+ const read_slots = new Set();
178
+
179
+ for (const read of instruction.reads) {
180
+ for (const slot of particle_read_slots(read)) {
181
+ if (slot < 0 || slot >= slots) {
182
+ return null;
183
+ }
184
+
185
+ read_slots.add(slot);
186
+ }
187
+ }
188
+
189
+ // After the write it reads.
190
+ for (const slot of read_slots) {
191
+ if (writer[slot] >= 0) {
192
+ predecessors[i].add(writer[slot]);
193
+ }
194
+ }
195
+
196
+ const write = instruction.write;
197
+
198
+ if (write !== null) {
199
+ if (write.base + write.span > slots) {
200
+ return null;
201
+ }
202
+
203
+ // After the previous write, and after every read of the value it replaces.
204
+ for (let lane = 0; lane < write.span; lane++) {
205
+ const slot = write.base + lane;
206
+
207
+ if (writer[slot] >= 0) {
208
+ predecessors[i].add(writer[slot]);
209
+ }
210
+
211
+ for (const reader of readers[slot]) {
212
+ predecessors[i].add(reader);
213
+ }
214
+ }
215
+ }
216
+
217
+ for (const slot of read_slots) {
218
+ readers[slot].push(i);
219
+ }
220
+
221
+ if (write !== null) {
222
+ for (let lane = 0; lane < write.span; lane++) {
223
+ writer[write.base + lane] = i;
224
+ readers[write.base + lane] = [];
225
+ }
226
+ }
227
+
228
+ // A barrier comes after everything above it — the previous barrier included, since two of
229
+ // them may be adjacent — and everything below it comes after it.
230
+ if (instruction.semantics.side_effects) {
231
+ for (let j = Math.max(barrier, 0); j < i; j++) {
232
+ predecessors[i].add(j);
233
+ }
234
+
235
+ barrier = i;
236
+ } else if (barrier >= 0) {
237
+ predecessors[i].add(barrier);
238
+ }
239
+
240
+ predecessors[i].delete(i);
241
+ }
242
+
243
+ return predecessors;
244
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"pass_share_subexpressions.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_share_subexpressions.js"],"names":[],"mappings":"AA0E6E,4JAGoC;AAtEjH,qBAAqB;AACrB,iDADW,MAAM,CACwD"}
1
+ {"version":3,"file":"pass_share_subexpressions.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_share_subexpressions.js"],"names":[],"mappings":"AA8GU,4JAM8C;AA7GxD,qBAAqB;AACrB,iDADW,MAAM,CACwD"}
@@ -1,151 +1,154 @@
1
- import { VM_OP, VM_OPERAND, vm_dest_width, vm_encode_word0 } from "../isa/ParticleVMISA.js";
2
- import {
3
- ParticleValueNumbering,
4
- decode_particle_instructions,
5
- particle_instruction_is_well_formed,
6
- } from "./particle_program_analysis.js";
7
-
8
- /** @type {string} */
9
- export const PARTICLE_PASS_SHARE_SUBEXPRESSIONS = "share_subexpressions";
10
-
11
- /**
12
- * Recognise an instruction that recomputes something a register already holds, and read the register
13
- * instead.
14
- *
15
- * Two executions of a shareable opcode over equal operands produce equal results, so the second is
16
- * a copy of the first — and where the two write the same register, it is not even that: the register
17
- * already holds the answer and the instruction goes entirely.
18
- *
19
- * Equality is by value number rather than by register: the same expression computed from registers
20
- * that have since been copied about still matches, and a register overwritten since fails the match
21
- * without any separate invalidation. It is the machinery `pass_propagate_copies` uses, asked a
22
- * different question.
23
- *
24
- * ## What is not shared
25
- *
26
- * `LOAD_ATTR` reads the record, which a `STORE_ATTR` in between may have changed, and `RANDOM` reads
27
- * the RNG, which every draw changes. Neither is shareable, so neither is ever considered here — the
28
- * `shareable` column of {@link ./particle_vm_semantics.js} is the whole of the rule, which is what
29
- * keeps the aliasing question from having to be answered a second time in this file.
30
- *
31
- * `ADD`, `MUL` and `CMP_EQ` match with their operands either way round. `MIN` and `MAX` do not,
32
- * although they look just as commutative: `min(-0, 0)` and `min(0, -0)` are different registers'
33
- * worth of zero, and the record is compared to the bit.
34
- *
35
- * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
36
- */
37
- export function pass_share_subexpressions(instructions, context) {
38
- const decoded = decode_particle_instructions(instructions);
39
- const values = new ParticleValueNumbering(context.register_slots);
40
-
41
- /** @type {Map<string, {base: number, ids: number[]}>} expression -> where its result was left */
42
- const available = new Map();
43
-
44
- /** @type {number[][]} */
45
- const out = [];
46
-
47
- let changed = false;
48
-
49
- for (const instruction of decoded) {
50
- const span = instruction.write === null ? 0 : vm_dest_width(instruction.op, instruction.width);
51
- const key = is_shareable(instruction) && span > 0 ? expression_key(instruction, values) : null;
52
- const previous = key === null ? undefined : available.get(key);
53
-
54
- let shared = false;
55
-
56
- if (previous !== undefined && values.holds(previous.base, previous.ids)) {
57
- const replacement = share(instruction, previous, span);
58
-
59
- if (replacement !== null) {
60
- for (const words of replacement) {
61
- out.push(words);
62
- values.publish(words);
63
- }
64
-
65
- shared = true;
66
- changed = true;
67
- }
68
- }
69
-
70
- if (!shared) {
71
- out.push(instruction.words);
72
- values.publish(instruction.words);
73
- }
74
-
75
- // Recorded after the write, so an expression that overwrites one of its own sources names
76
- // the register as it stands once the instruction has run.
77
- if (key !== null && !shared) {
78
- available.set(key, { base: instruction.write.base, ids: values.ids_of(instruction.write.base, span) });
79
- }
80
- }
81
-
82
- return changed ? out : null;
83
- }
84
-
85
- /**
86
- * `MOV` is shareable in the sense the semantics table means, but it is not shared here: replacing
87
- * one copy with another copy is no gain, and `pass_propagate_copies` — which reads THROUGH copies —
88
- * would immediately rewrite the result back, leaving the two passes trading the same instruction
89
- * between them for as many sweeps as they are given.
90
- *
91
- * @param {import("./particle_program_analysis.js").ParticleDecodedInstruction} instruction
92
- * @returns {boolean}
93
- */
94
- function is_shareable(instruction) {
95
- return instruction.semantics.shareable && instruction.op !== VM_OP.MOV;
96
- }
97
-
98
- /** Opcodes whose two register operands may be matched either way round. */
99
- const COMMUTATIVE = new Set([VM_OP.ADD, VM_OP.MUL, VM_OP.CMP_EQ]);
100
-
101
- /**
102
- * What makes two executions the same one: the opcode, the width, every immediate, and the value
103
- * numbers behind every lane an operand reads.
104
- *
105
- * @returns {string|null} `null` when an operand reaches outside the file, which is nothing to match
106
- */
107
- function expression_key(instruction, values) {
108
- /** @type {Map<number, string>} */
109
- const operands = new Map();
110
-
111
- for (const read of instruction.reads) {
112
- const ids = values.ids_of(read.base, read.span);
113
-
114
- if (ids === null) {
115
- return null;
116
- }
117
-
118
- operands.set(read.operand, ids.join(","));
119
- }
120
-
121
- /** @type {string[]} */
122
- const parts = [];
123
-
124
- for (let slot = 0; slot < 3; slot++) {
125
- parts.push(
126
- instruction.meta.operands[slot] === VM_OPERAND.REG
127
- ? `r${operands.get(slot)}`
128
- : `i${instruction.words[2 + slot]}`
129
- );
130
- }
131
-
132
- if (COMMUTATIVE.has(instruction.op)) {
133
- parts.sort();
134
- }
135
-
136
- return `${instruction.op}.${instruction.width}|${parts.join("|")}`;
137
- }
138
-
139
- /**
140
- * @returns {number[][]|null} what to emit instead — nothing at all when the result is already in the
141
- * destination, otherwise a copy of it — or `null` when the copy would not be a legal instruction
142
- */
143
- function share(instruction, previous, span) {
144
- if (previous.base === instruction.write.base) {
145
- return [];
146
- }
147
-
148
- const words = [vm_encode_word0(VM_OP.MOV, span), instruction.write.base, previous.base, 0, 0];
149
-
150
- return particle_instruction_is_well_formed(words) ? [words] : null;
151
- }
1
+ import { VM_KIND, VM_OP, vm_dest_width, vm_pack_instruction } from "../isa/ParticleVMISA.js";
2
+ import {
3
+ ParticleValueNumbering,
4
+ decode_particle_instructions,
5
+ particle_instruction_is_well_formed,
6
+ } from "./particle_program_analysis.js";
7
+
8
+ /** @type {string} */
9
+ export const PARTICLE_PASS_SHARE_SUBEXPRESSIONS = "share_subexpressions";
10
+
11
+ /**
12
+ * Recognise an instruction that recomputes something a register already holds, and read the register
13
+ * instead.
14
+ *
15
+ * Two executions of a shareable opcode over equal operands produce equal results, so the second is
16
+ * a copy of the first — and where the two write the same register, it is not even that: the register
17
+ * already holds the answer and the instruction goes entirely.
18
+ *
19
+ * Equality is by value number rather than by register: the same expression computed from registers
20
+ * that have since been copied about still matches, and a register overwritten since fails the match
21
+ * without any separate invalidation. It is the machinery `pass_propagate_copies` uses, asked a
22
+ * different question. A register operand contributes the numbers of the lanes it reads, through its
23
+ * swizzle, so `r0.xxx` and `r4.yyy` match when r0 and r5 hold the same value; a literal contributes
24
+ * itself.
25
+ *
26
+ * ## What is not shared
27
+ *
28
+ * `LOAD_ATTR` reads the record, which a `STORE_ATTR` in between may have changed, and `RANDOM` reads
29
+ * the RNG, which every draw changes. Neither is shareable, so neither is ever considered here — the
30
+ * `shareable` column of {@link ./particle_vm_semantics.js} is the whole of the rule, which is what
31
+ * keeps the aliasing question from having to be answered a second time in this file.
32
+ *
33
+ * `ADD`, `MUL` and `CMP_EQ` match with their operands either way round. `MIN` and `MAX` do not,
34
+ * although they look just as commutative: `min(-0, 0)` and `min(0, -0)` are different registers'
35
+ * worth of zero, and the record is compared to the bit.
36
+ *
37
+ * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
38
+ */
39
+ export function pass_share_subexpressions(instructions, context) {
40
+ const decoded = decode_particle_instructions(instructions);
41
+ const values = new ParticleValueNumbering(context.register_slots);
42
+
43
+ /** @type {Map<string, {base: number, ids: number[]}>} expression -> where its result was left */
44
+ const available = new Map();
45
+
46
+ /** @type {number[][]} */
47
+ const out = [];
48
+
49
+ let changed = false;
50
+
51
+ for (const instruction of decoded) {
52
+ const span = instruction.write === null ? 0 : vm_dest_width(instruction.op, instruction.width);
53
+ const key = is_shareable(instruction) && span > 0 ? expression_key(instruction, values) : null;
54
+ const previous = key === null ? undefined : available.get(key);
55
+
56
+ let shared = false;
57
+
58
+ if (previous !== undefined && values.holds(previous.base, previous.ids)) {
59
+ const replacement = share(instruction, previous, span);
60
+
61
+ if (replacement !== null) {
62
+ for (const words of replacement) {
63
+ out.push(words);
64
+ values.publish(words);
65
+ }
66
+
67
+ shared = true;
68
+ changed = true;
69
+ }
70
+ }
71
+
72
+ if (!shared) {
73
+ out.push(instruction.words);
74
+ values.publish(instruction.words);
75
+ }
76
+
77
+ // Recorded after the write, so an expression that overwrites one of its own sources names
78
+ // the register as it stands once the instruction has run.
79
+ if (key !== null && !shared) {
80
+ available.set(key, { base: instruction.write.base, ids: values.ids_of(instruction.write.base, span) });
81
+ }
82
+ }
83
+
84
+ return changed ? out : null;
85
+ }
86
+
87
+ /**
88
+ * `MOV` is shareable in the sense the semantics table means, but it is not shared here: replacing
89
+ * one copy with another copy is no gain, and `pass_propagate_copies` — which reads THROUGH copies —
90
+ * would immediately rewrite the result back, leaving the two passes trading the same instruction
91
+ * between them for as many sweeps as they are given.
92
+ *
93
+ * @param {import("./particle_program_analysis.js").ParticleDecodedInstruction} instruction
94
+ * @returns {boolean}
95
+ */
96
+ function is_shareable(instruction) {
97
+ return instruction.semantics.shareable && instruction.op !== VM_OP.MOV;
98
+ }
99
+
100
+ /** Opcodes whose two register operands may be matched either way round. */
101
+ const COMMUTATIVE = new Set([VM_OP.ADD, VM_OP.MUL, VM_OP.CMP_EQ]);
102
+
103
+ /**
104
+ * What makes two executions the same one: the opcode, the width, every raw field, and per source
105
+ * either the value numbers behind the lanes it reads or the literal it is.
106
+ *
107
+ * @returns {string|null} `null` when an operand reaches outside the file, which is nothing to match
108
+ */
109
+ function expression_key(instruction, values) {
110
+ /** @type {string[]} */
111
+ const parts = [];
112
+
113
+ for (let slot = 0; slot < 3; slot++) {
114
+ const source = instruction.sources.find(candidate => candidate.operand === slot);
115
+
116
+ if (source === undefined) {
117
+ parts.push(`i${instruction.words[1 + slot]}`);
118
+ } else if (source.kind === VM_KIND.IMM) {
119
+ parts.push(`#${source.word}`);
120
+ } else {
121
+ const ids = values.ids_read(source);
122
+
123
+ if (ids === null) {
124
+ return null;
125
+ }
126
+
127
+ parts.push(`r${ids.join(",")}`);
128
+ }
129
+ }
130
+
131
+ if (COMMUTATIVE.has(instruction.op)) {
132
+ parts.sort();
133
+ }
134
+
135
+ return `${instruction.op}.${instruction.width}|${parts.join("|")}`;
136
+ }
137
+
138
+ /**
139
+ * @returns {number[][]|null} what to emit instead — nothing at all when the result is already in the
140
+ * destination, otherwise a copy of it — or `null` when the copy would not be a legal instruction
141
+ */
142
+ function share(instruction, previous, span) {
143
+ if (previous.base === instruction.write.base) {
144
+ return [];
145
+ }
146
+
147
+ const words = vm_pack_instruction(
148
+ VM_OP.MOV, span, instruction.write.base,
149
+ [VM_KIND.REG, VM_KIND.NONE, VM_KIND.NONE],
150
+ [previous.base, 0, 0]
151
+ );
152
+
153
+ return particle_instruction_is_well_formed(words) ? [words] : null;
154
+ }
@@ -32,6 +32,26 @@ export function particle_scene_fixture(): ParticleSceneFixture;
32
32
  * @returns {ParticleEmitter}
33
33
  */
34
34
  export function place_emitter(fixture: ParticleSceneFixture, config: ParticleEmitter | object, parent?: import("../scene/Node3D.js").Node3D): ParticleEmitter;
35
+ /**
36
+ * What the fixture's registry assigned an emitter: its table row, its generation, the heap
37
+ * placement of its program, the atlas patch. The emitter carries none of it — see
38
+ * {@link ./runtime/GPUParticleEmitterContext.js} — so a spec that wants the row a particle header
39
+ * should carry asks the registry, the way the passes' own callers do.
40
+ *
41
+ * @param {ParticleSceneFixture} fixture
42
+ * @param {ParticleEmitter} emitter
43
+ * @returns {import("./runtime/GPUParticleEmitterContext.js").GPUParticleEmitterContext}
44
+ */
45
+ export function emitter_context(fixture: ParticleSceneFixture, emitter: ParticleEmitter): import("./runtime/GPUParticleEmitterContext.js").GPUParticleEmitterContext;
46
+ /**
47
+ * The emitter table row an emitter was given — {@link emitter_context}`.row`, which specs index
48
+ * per-emitter buffers with often enough to be worth naming.
49
+ *
50
+ * @param {ParticleSceneFixture} fixture
51
+ * @param {ParticleEmitter} emitter
52
+ * @returns {number}
53
+ */
54
+ export function emitter_row(fixture: ParticleSceneFixture, emitter: ParticleEmitter): number;
35
55
  /**
36
56
  * The two databases as the `array<u32>` buffers the particle shaders bind. Call after the last
37
57
  * change to either; it flushes both.
@@ -1 +1 @@
1
- {"version":3,"file":"particle_test_fixtures.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/particle_test_fixtures.js"],"names":[],"mappings":"AAWA;;;;;;;;;GASG;AAEH;;;;;;;GAOG;AAEH;;;;GAIG;AACH,0CAFa,oBAAoB,CAUhC;AAED;;;;;;;;GAQG;AACH,uCALW,oBAAoB,UACpB,eAAe,GAAC,MAAM,WACtB,OAAO,oBAAoB,EAAE,MAAM,GACjC,eAAe,CAkB3B;AAED;;;;;;GAMG;AACH,iDAHW,oBAAoB,GAClB;IAAC,cAAc,EAAE,WAAW,CAAC;IAAC,gBAAgB,EAAE,WAAW,CAAA;CAAC,CAUxE;AAED;;;;;;GAMG;AACH,qCAJW,MAAM,SACN,MAAM,GACJ;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,EAAE,CAI7B;AAED;;;;GAIG;AACH,qCAFa;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,EAAE,CAI7B;AA2BD;;;;;;GAMG;AACH,qDAJW,WAAW,OACX,MAAM,GACJ;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAalG;AAED;;;;;;;GAOG;AACH,sDAJW,WAAW,OACX,MAAM,UACN;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,QAWrG;AAED;;;;;;;GAOG;AACH,sCAJW,MAAM,aACN,UAAU,MAAM,CAAC,GACf;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAC,CAIlD;AAED;;;;;;GAMG;AACH,2CAHW;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAC,GACpC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAC,CAWlD;;YAlLa,iBAAiB;cACjB,eAAe;WACf,KAAK;mBACL,OAAO,6BAA6B,EAAE,eAAe;cACrD,eAAe;;gCAnBG,8BAA8B;kCAT5B,wCAAwC;gCAC1C,uBAAuB;sBAEjC,mBAAmB;gCAKT,8BAA8B"}
1
+ {"version":3,"file":"particle_test_fixtures.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/particle_test_fixtures.js"],"names":[],"mappings":"AAWA;;;;;;;;;GASG;AAEH;;;;;;;GAOG;AAEH;;;;GAIG;AACH,0CAFa,oBAAoB,CAUhC;AAED;;;;;;;;GAQG;AACH,uCALW,oBAAoB,UACpB,eAAe,GAAC,MAAM,WACtB,OAAO,oBAAoB,EAAE,MAAM,GACjC,eAAe,CAkB3B;AAED;;;;;;;;;GASG;AACH,yCAJW,oBAAoB,WACpB,eAAe,GACb,OAAO,wCAAwC,EAAE,yBAAyB,CAItF;AAED;;;;;;;GAOG;AACH,qCAJW,oBAAoB,WACpB,eAAe,GACb,MAAM,CAIlB;AAED;;;;;;GAMG;AACH,iDAHW,oBAAoB,GAClB;IAAC,cAAc,EAAE,WAAW,CAAC;IAAC,gBAAgB,EAAE,WAAW,CAAA;CAAC,CAUxE;AAED;;;;;;GAMG;AACH,qCAJW,MAAM,SACN,MAAM,GACJ;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,EAAE,CAI7B;AAED;;;;GAIG;AACH,qCAFa;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,EAAE,CAI7B;AA2BD;;;;;;GAMG;AACH,qDAJW,WAAW,OACX,MAAM,GACJ;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAalG;AAED;;;;;;;GAOG;AACH,sDAJW,WAAW,OACX,MAAM,UACN;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,QAWrG;AAED;;;;;;;GAOG;AACH,sCAJW,MAAM,aACN,UAAU,MAAM,CAAC,GACf;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAC,CAIlD;AAED;;;;;;GAMG;AACH,2CAHW;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAC,GACpC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAC,CAWlD;;YA5Ma,iBAAiB;cACjB,eAAe;WACf,KAAK;mBACL,OAAO,6BAA6B,EAAE,eAAe;cACrD,eAAe;;gCAnBG,8BAA8B;kCAT5B,wCAAwC;gCAC1C,uBAAuB;sBAEjC,mBAAmB;gCAKT,8BAA8B"}