@woosh/meep-engine 3.16.0 → 3.17.1

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 (431) hide show
  1. package/README.md +8 -72
  2. package/editor/particles/effect/ParticleEffectDocument.d.ts +21 -6
  3. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  4. package/editor/particles/effect/ParticleEffectDocument.js +38 -17
  5. package/editor/view/node-graph/NodeGraphClipboard.d.ts +186 -0
  6. package/editor/view/node-graph/NodeGraphClipboard.d.ts.map +1 -0
  7. package/editor/view/node-graph/NodeGraphClipboard.js +231 -0
  8. package/editor/view/node-graph/NodeGraphEditorView.d.ts +59 -1
  9. package/editor/view/node-graph/NodeGraphEditorView.d.ts.map +1 -1
  10. package/editor/view/node-graph/NodeGraphEditorView.js +248 -5
  11. package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
  12. package/editor/view/node-graph/NodeGraphView.js +84 -8
  13. package/editor/view/node-graph/actions/connection_bind_actions.d.ts +23 -0
  14. package/editor/view/node-graph/actions/connection_bind_actions.d.ts.map +1 -0
  15. package/editor/view/node-graph/actions/connection_bind_actions.js +39 -0
  16. package/editor/view/particles/effect/ParticleCodeEditorView.d.ts.map +1 -1
  17. package/editor/view/particles/effect/ParticleCodeEditorView.js +4 -3
  18. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts +20 -0
  19. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -0
  20. package/editor/view/particles/effect/ParticleCurveEditorView.js +574 -0
  21. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
  22. package/editor/view/particles/effect/ParticleEmitterInspectorView.js +27 -1
  23. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts +24 -0
  24. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -0
  25. package/editor/view/particles/effect/ParticleGradientEditorView.js +472 -0
  26. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts +5 -0
  27. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts.map +1 -1
  28. package/editor/view/particles/effect/ParticleGraphEditorView.js +61 -31
  29. package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
  30. package/editor/view/particles/effect/ParticleNodeParametersView.js +33 -0
  31. package/editor/view/particles/effect/particle-editor.css +123 -35
  32. package/package.json +1 -1
  33. package/src/core/binary/allocator/OffsetAllocator.d.ts +25 -16
  34. package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
  35. package/src/core/binary/allocator/OffsetAllocator.js +10 -1
  36. package/src/core/collection/array/typed/float32_array_hash.d.ts +21 -0
  37. package/src/core/collection/array/typed/float32_array_hash.d.ts.map +1 -0
  38. package/src/core/collection/array/typed/float32_array_hash.js +38 -0
  39. package/src/core/graph/csr/CSRGraph.d.ts +8 -1
  40. package/src/core/graph/csr/CSRGraph.d.ts.map +1 -1
  41. package/src/core/graph/csr/CSRGraph.js +14 -6
  42. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts +24 -0
  43. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts.map +1 -1
  44. package/src/core/model/node-graph/visual/layout/LayoutProblem.js +27 -0
  45. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +26 -0
  46. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
  47. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +28 -0
  48. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts +92 -3
  49. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts.map +1 -1
  50. package/src/core/model/node-graph/visual/layout/RouteGrid.js +405 -242
  51. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts +50 -5
  52. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts.map +1 -1
  53. package/src/core/model/node-graph/visual/layout/RouteSearch.js +160 -24
  54. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts +7 -0
  55. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts.map +1 -1
  56. package/src/core/model/node-graph/visual/layout/RouteSet.js +8 -0
  57. package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +9 -3
  58. package/src/core/model/node-graph/visual/layout/layout_build_problem.d.ts.map +1 -1
  59. package/src/core/model/node-graph/visual/layout/layout_build_problem.js +7 -0
  60. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts +9 -3
  61. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +1 -1
  62. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.js +17 -3
  63. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts +9 -6
  64. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts.map +1 -1
  65. package/src/core/model/node-graph/visual/layout/layout_node_graph.js +49 -7
  66. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts +11 -1
  67. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +1 -1
  68. package/src/core/model/node-graph/visual/layout/layout_order_layers.js +135 -16
  69. package/src/core/model/node-graph/visual/layout/route_connections.d.ts +29 -0
  70. package/src/core/model/node-graph/visual/layout/route_connections.d.ts.map +1 -1
  71. package/src/core/model/node-graph/visual/layout/route_connections.js +716 -309
  72. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts +3 -2
  73. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts.map +1 -1
  74. package/src/core/model/node-graph/visual/layout/route_grid_build.js +7 -15
  75. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts +6 -0
  76. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts.map +1 -1
  77. package/src/core/model/node-graph/visual/layout/route_nudge.js +42 -13
  78. package/src/engine/animation/AnimationUtils.js +246 -246
  79. package/src/engine/animation/Animations.js +74 -74
  80. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2078 -2078
  81. package/src/engine/ecs/EventType.d.ts +0 -1
  82. package/src/engine/ecs/EventType.js +1 -26
  83. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +1 -1
  84. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +1 -1
  85. package/src/engine/ecs/ik/ik_write_local_rotation.js +3 -7
  86. package/src/engine/ecs/parent/EntityNode.d.ts.map +1 -1
  87. package/src/engine/ecs/parent/EntityNode.js +4 -9
  88. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
  89. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +360 -364
  90. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts +41 -0
  91. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts.map +1 -0
  92. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.js +40 -0
  93. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +8 -0
  94. package/src/engine/ecs/transform/t64_announce_change.d.ts +10 -7
  95. package/src/engine/ecs/transform/t64_announce_change.d.ts.map +1 -1
  96. package/src/engine/ecs/transform/t64_announce_change.js +12 -12
  97. package/src/engine/ecs/transform/t64_set_rotation_axis_angle.d.ts +25 -0
  98. package/src/engine/ecs/transform/t64_set_rotation_axis_angle.d.ts.map +1 -0
  99. package/src/engine/ecs/transform/t64_set_rotation_axis_angle.js +45 -0
  100. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts +30 -0
  101. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts.map +1 -0
  102. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js +29 -0
  103. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
  104. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +13 -21
  105. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
  106. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +4 -8
  107. package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
  108. package/src/engine/graphics3/LightSystem.js +4 -8
  109. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  110. package/src/engine/graphics3/MeshSystem.js +9 -19
  111. package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -1
  112. package/src/engine/graphics3/ParticleEmitterSystem.js +4 -8
  113. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  114. package/src/engine/graphics3/ShadedGeometrySystem.js +4 -10
  115. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts +1 -1
  116. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts.map +1 -1
  117. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +4 -8
  118. package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.js +218 -218
  119. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  120. package/src/engine/physics/ecs/PhysicsSystem.js +2 -5
  121. package/src/engine/sound/ecs/SoundListenerSystem.d.ts.map +1 -1
  122. package/src/engine/sound/ecs/SoundListenerSystem.js +6 -8
  123. package/src/engine/sound/simulation/AcousticSimulator.d.ts +11 -8
  124. package/src/engine/sound/simulation/AcousticSimulator.d.ts.map +1 -1
  125. package/src/engine/sound/simulation/AcousticSimulator.js +45 -36
  126. package/src/engine/sound/simulation/README.md +2 -2
  127. package/src/engine/sound/simulation/core/OcclusionSolver.d.ts.map +1 -1
  128. package/src/engine/sound/simulation/core/VolumeField.d.ts +9 -9
  129. package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
  130. package/src/engine/sound/simulation/core/VolumeField.js +29 -13
  131. package/src/engine/sound/simulation/core/acoustic_occlusion_solve.d.ts +31 -0
  132. package/src/engine/sound/simulation/core/acoustic_occlusion_solve.d.ts.map +1 -0
  133. package/src/engine/sound/simulation/core/acoustic_occlusion_solve.js +134 -0
  134. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts +0 -4
  135. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts.map +1 -1
  136. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +5 -11
  137. package/src/shade/playground/particle_editor/README.md +43 -2
  138. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  139. package/src/shade/playground/particle_system/particle_prototype.js +4 -5
  140. package/src/shade/playground/particle_system/particle_scene.js +4 -4
  141. package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
  142. package/src/shade/playground/volumetrics_froxel/main.js +6 -1
  143. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  144. package/src/shade/renderer/Renderer.js +13 -1
  145. package/src/shade/renderer/particles/DESIGN.md +104 -19
  146. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +64 -50
  147. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  148. package/src/shade/renderer/particles/GPUParticleSystem.js +176 -78
  149. package/src/shade/renderer/particles/ParticleConstants.d.ts +59 -23
  150. package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
  151. package/src/shade/renderer/particles/ParticleConstants.js +66 -23
  152. package/src/shade/renderer/particles/ParticleRenderMode.d.ts +19 -0
  153. package/src/shade/renderer/particles/ParticleRenderMode.d.ts.map +1 -0
  154. package/src/shade/renderer/particles/ParticleRenderMode.js +33 -0
  155. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  156. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +167 -166
  157. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts +37 -0
  158. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -0
  159. package/src/shade/renderer/particles/data/particle_emitter_record.js +109 -0
  160. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +3 -3
  161. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +303 -303
  162. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +18 -0
  163. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -1
  164. package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +152 -133
  165. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +0 -11
  166. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
  167. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +720 -621
  168. package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
  169. package/src/shade/renderer/particles/graph/compile_particle_graph.js +8 -3
  170. package/src/shade/renderer/particles/graph/flatten_particle_graph.d.ts.map +1 -1
  171. package/src/shade/renderer/particles/graph/flatten_particle_graph.js +244 -213
  172. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
  173. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +6 -0
  174. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
  175. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +294 -319
  176. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.d.ts.map +1 -1
  177. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.js +524 -517
  178. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts +22 -0
  179. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts.map +1 -0
  180. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.js +517 -0
  181. package/src/shade/renderer/particles/graph/groups/simplex_reference.d.ts.map +1 -1
  182. package/src/shade/renderer/particles/graph/groups/simplex_reference.js +185 -159
  183. package/src/shade/renderer/particles/graph/make_particle_group.d.ts.map +1 -1
  184. package/src/shade/renderer/particles/graph/make_particle_group.js +2 -20
  185. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts +17 -0
  186. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts.map +1 -0
  187. package/src/shade/renderer/particles/graph/particle_compare_ops.js +22 -0
  188. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts +28 -8
  189. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts.map +1 -1
  190. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.js +49 -25
  191. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +40 -0
  192. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
  193. package/src/shade/renderer/particles/graph/particle_node_parameters.js +312 -234
  194. package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
  195. package/src/shade/renderer/particles/graph/particle_node_presentation.js +59 -3
  196. package/src/shade/renderer/particles/graph/particle_ramp.d.ts +230 -0
  197. package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -0
  198. package/src/shade/renderer/particles/graph/particle_ramp.js +403 -0
  199. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts +7 -1
  200. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts.map +1 -1
  201. package/src/shade/renderer/particles/graph/validate_particle_graph.js +66 -10
  202. package/src/shade/renderer/particles/graph_particles.d.ts +23 -69
  203. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  204. package/src/shade/renderer/particles/graph_particles.js +105 -262
  205. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  206. package/src/shade/renderer/particles/graph_particles_avboit.js +3 -2
  207. package/src/shade/renderer/particles/graph_particles_billboard.d.ts +37 -0
  208. package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +1 -0
  209. package/src/shade/renderer/particles/graph_particles_billboard.js +93 -0
  210. package/src/shade/renderer/particles/isa/InstructionStream.d.ts +51 -22
  211. package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
  212. package/src/shade/renderer/particles/isa/InstructionStream.js +98 -38
  213. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts +49 -8
  214. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts.map +1 -1
  215. package/src/shade/renderer/particles/isa/ParticleProgram.js +95 -150
  216. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +306 -64
  217. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
  218. package/src/shade/renderer/particles/isa/ParticleVMISA.js +505 -136
  219. package/src/shade/renderer/particles/isa/particle_assembly.d.ts +36 -12
  220. package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
  221. package/src/shade/renderer/particles/isa/particle_assembly.js +354 -139
  222. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts +9 -0
  223. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts.map +1 -0
  224. package/src/shade/renderer/particles/isa/validate_particle_program.js +128 -0
  225. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts +23 -0
  226. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
  227. package/src/shade/renderer/particles/layout/ParticleLayout.js +68 -0
  228. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts +77 -0
  229. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts.map +1 -0
  230. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.js +219 -0
  231. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts +83 -0
  232. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -0
  233. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +283 -0
  234. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +133 -0
  235. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts.map +1 -0
  236. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +334 -0
  237. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts +117 -0
  238. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts.map +1 -0
  239. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.js +70 -0
  240. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts +97 -0
  241. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts.map +1 -0
  242. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +462 -0
  243. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts +116 -0
  244. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts.map +1 -0
  245. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js +687 -0
  246. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts +57 -0
  247. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts.map +1 -0
  248. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +860 -0
  249. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts +115 -0
  250. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts.map +1 -0
  251. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.js +264 -0
  252. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +81 -42
  253. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
  254. package/src/shade/renderer/particles/optimizer/optimize_particle_program.js +477 -478
  255. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts +100 -0
  256. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts.map +1 -0
  257. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.js +236 -0
  258. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts +139 -59
  259. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
  260. package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +764 -647
  261. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts +40 -7
  262. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
  263. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +376 -213
  264. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts +30 -3
  265. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
  266. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +337 -223
  267. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +24 -38
  268. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
  269. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +166 -206
  270. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts +99 -0
  271. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts.map +1 -0
  272. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.js +313 -0
  273. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts +3 -2
  274. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts.map +1 -1
  275. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.js +198 -197
  276. package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.d.ts.map +1 -1
  277. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts +19 -0
  278. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
  279. package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +678 -561
  280. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts +22 -0
  281. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts.map +1 -0
  282. package/src/shade/renderer/particles/optimizer/pass_inline_constants.js +221 -0
  283. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.d.ts.map +1 -1
  284. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.js +63 -72
  285. package/src/shade/renderer/particles/optimizer/pass_pack_registers.d.ts.map +1 -1
  286. package/src/shade/renderer/particles/optimizer/pass_pack_registers.js +87 -86
  287. package/src/shade/renderer/particles/optimizer/pass_peephole.d.ts.map +1 -1
  288. package/src/shade/renderer/particles/optimizer/pass_peephole.js +392 -271
  289. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.d.ts.map +1 -1
  290. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.js +361 -268
  291. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts +4 -0
  292. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts.map +1 -0
  293. package/src/shade/renderer/particles/optimizer/pass_schedule.js +244 -0
  294. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.d.ts.map +1 -1
  295. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.js +154 -151
  296. package/src/shade/renderer/particles/particle_test_fixtures.d.ts +20 -0
  297. package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +1 -1
  298. package/src/shade/renderer/particles/particle_test_fixtures.js +229 -203
  299. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +99 -25
  300. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  301. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +438 -286
  302. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +109 -0
  303. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -0
  304. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +127 -0
  305. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +87 -102
  306. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  307. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +184 -163
  308. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts +130 -0
  309. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts.map +1 -0
  310. package/src/shade/renderer/particles/runtime/ProgramHeap.js +595 -0
  311. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts +91 -0
  312. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts.map +1 -0
  313. package/src/shade/renderer/particles/runtime/ProgramPlacement.js +106 -0
  314. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +5 -2
  315. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
  316. package/src/shade/renderer/particles/runtime/create_particle_effect.js +22 -19
  317. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts +28 -0
  318. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts.map +1 -0
  319. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.js +136 -0
  320. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts +35 -0
  321. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts.map +1 -0
  322. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.js +133 -0
  323. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts +18 -9
  324. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  325. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +20 -80
  326. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts +33 -0
  327. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -0
  328. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +114 -0
  329. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts +8 -0
  330. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  331. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +33 -101
  332. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts +45 -0
  333. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -0
  334. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +123 -0
  335. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +51 -0
  336. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +1 -0
  337. package/src/shade/renderer/particles/sort/graph_particle_sort.js +120 -0
  338. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts +6 -0
  339. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts.map +1 -0
  340. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.js +16 -0
  341. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +4 -1
  342. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  343. package/src/shade/renderer/particles/vm/ParticleVMReference.js +261 -140
  344. package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
  345. package/src/shade/renderer/particles/vm/chunk_particle_vm.js +217 -255
  346. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts +43 -0
  347. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts.map +1 -0
  348. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.js +55 -0
  349. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts +62 -0
  350. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts.map +1 -0
  351. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.js +86 -0
  352. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts +22 -0
  353. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts.map +1 -0
  354. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.js +32 -0
  355. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts +9 -0
  356. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts.map +1 -0
  357. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.js +19 -0
  358. package/src/shade/renderer/shader/chunk/noise/psrdnoise/README.md +65 -0
  359. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts +24 -0
  360. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts.map +1 -0
  361. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.js +83 -0
  362. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts +25 -0
  363. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts.map +1 -0
  364. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.js +42 -0
  365. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts +31 -0
  366. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts.map +1 -0
  367. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.js +80 -0
  368. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts +26 -0
  369. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts.map +1 -0
  370. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.js +109 -0
  371. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts +38 -0
  372. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts.map +1 -0
  373. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.js +129 -0
  374. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts +21 -0
  375. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts.map +1 -0
  376. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.js +35 -0
  377. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts +19 -0
  378. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts.map +1 -0
  379. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.js +28 -0
  380. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts +13 -0
  381. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts.map +1 -0
  382. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.js +22 -0
  383. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts +22 -0
  384. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts.map +1 -0
  385. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.js +59 -0
  386. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts +23 -0
  387. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts.map +1 -0
  388. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.js +74 -0
  389. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +7 -0
  390. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
  391. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +7 -0
  392. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts +34 -1
  393. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts.map +1 -1
  394. package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +41 -1
  395. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +3 -2
  396. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  397. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +49 -10
  398. package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
  399. package/src/view/minimap/dom/MinimapCameraView.js +4 -9
  400. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts +0 -15
  401. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts.map +0 -1
  402. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts +0 -45
  403. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts.map +0 -1
  404. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts +0 -24
  405. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts.map +0 -1
  406. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts +0 -19
  407. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts.map +0 -1
  408. package/src/engine/ecs/transform/__probe.d.ts +0 -4
  409. package/src/engine/ecs/transform/__probe.d.ts.map +0 -1
  410. package/src/engine/ecs/util/hideEntityGracefully.d.ts +0 -9
  411. package/src/engine/ecs/util/hideEntityGracefully.d.ts.map +0 -1
  412. package/src/engine/sound/simulation/core/OcclusionSolver.js +0 -112
  413. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts +0 -27
  414. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts.map +0 -1
  415. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts +0 -14
  416. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +0 -1
  417. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts +0 -156
  418. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts.map +0 -1
  419. package/src/shade/renderer/particles/runtime/Emitter.d.ts +0 -219
  420. package/src/shade/renderer/particles/runtime/Emitter.d.ts.map +0 -1
  421. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts +0 -77
  422. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts.map +0 -1
  423. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts +0 -89
  424. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts.map +0 -1
  425. package/src/shade/renderer/particles/runtime/ProgramArena.js +0 -155
  426. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts +0 -15
  427. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts.map +0 -1
  428. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts +0 -34
  429. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts.map +0 -1
  430. package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts +0 -32
  431. 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"}