@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
@@ -1 +1 @@
1
- {"version":3,"file":"pass_propagate_copies.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_propagate_copies.js"],"names":[],"mappings":"AA2EsC,wJAStB;AA1EhB,qBAAqB;AACrB,6CADW,MAAM,CACgD"}
1
+ {"version":3,"file":"pass_propagate_copies.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_propagate_copies.js"],"names":[],"mappings":"AAwHe,wJAOX;AArHJ,qBAAqB;AACrB,6CADW,MAAM,CACgD"}
@@ -1,268 +1,361 @@
1
- import { VM_OP, vm_decode_op, vm_encode_word0 } from "../isa/ParticleVMISA.js";
2
- import {
3
- ParticleValueNumbering,
4
- decode_particle_instructions,
5
- particle_instruction_is_well_formed,
6
- particle_run_is_dead_after,
7
- particle_run_is_touched_between,
8
- particle_runs_overlap,
9
- } from "./particle_program_analysis.js";
10
-
11
- /** @type {string} */
12
- export const PARTICLE_PASS_PROPAGATE_COPIES = "propagate_copies";
13
-
14
- /**
15
- * Get rid of copies — by reading past them where the original is still intact, and by having the
16
- * instruction that produced the value write where the copy was going.
17
- *
18
- * Copies are most of what a broadcast is. The node compiler widens a scalar with a `SWIZZLE` because
19
- * some consumer asked for four lanes; when the lanes that survive are the ones the scalar was
20
- * already in, the broadcast is a register renaming and nothing else.
21
- *
22
- * ## Reading past a copy
23
- *
24
- * Every write gives its lanes a fresh value number and records the slot the value was ORIGINALLY
25
- * computed in; a copy inherits both. A read of a run can then be redirected to that original, as
26
- * long as the original still holds it — which is exactly "the value numbers still match", so a slot
27
- * overwritten since fails the test rather than needing a separate invalidation.
28
- *
29
- * A run is redirected only when its lanes trace back to CONSECUTIVE original slots. Two lanes of a
30
- * broadcast trace back to the same one, which is not a run and stays where it is.
31
- *
32
- * ## Writing where the copy was going
33
- *
34
- * `MOV d, s` where `s` was produced by one instruction, read by nothing but this copy, and dead
35
- * afterwards is that instruction writing to the wrong register. Retargeting it and dropping the copy
36
- * is what turns the graph compiler's broadcast-and-select into the two-lane value hand-written
37
- * assembly would have built directly.
38
- *
39
- * The conditions are the obvious ones and all of them are checked: nothing between the producer and
40
- * the copy may read the source or touch the destination, nothing after may read the source, and the
41
- * retargeted instruction still has to satisfy the operand-overlap rule. Retargeting a `RANDOM` is
42
- * allowed — where its result lands is not part of the draw sequence.
43
- *
44
- * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
45
- */
46
- export function pass_propagate_copies(instructions, context) {
47
- const rounds = context.max_iterations ?? 3;
48
-
49
- let current = instructions;
50
- let changed = false;
51
-
52
- for (let round = 0; round < rounds; round++) {
53
- const redirected = redirect_reads(current, context);
54
- const forwarded = forward_destinations(redirected ?? current);
55
-
56
- if (redirected === null && forwarded === null) {
57
- break;
58
- }
59
-
60
- current = forwarded ?? redirected;
61
- changed = true;
62
- }
63
-
64
- return changed ? current : null;
65
- }
66
-
67
- /**
68
- * Rewrite reads to name the slot the value was first computed in, and reduce the copies that are
69
- * spelled as something else — an identity `SWIZZLE` is a `MOV`, and a `MOV` onto its own source is
70
- * nothing at all.
71
- *
72
- * @param {number[][]} instructions
73
- * @param {object} context
74
- * @returns {number[][]|null}
75
- */
76
- function redirect_reads(instructions, context) {
77
- const decoded = decode_particle_instructions(instructions);
78
- const values = new ParticleValueNumbering(context.register_slots);
79
-
80
- /** @type {number[][]} */
81
- const out = [];
82
-
83
- let changed = false;
84
-
85
- for (const instruction of decoded) {
86
- let words = instruction.words;
87
-
88
- for (const read of instruction.reads) {
89
- const candidate = redirect(words, read, values);
90
-
91
- if (candidate !== null) {
92
- words = candidate;
93
- changed = true;
94
- }
95
- }
96
-
97
- const reduced = reduce_copy(words, instruction);
98
-
99
- if (reduced !== null) {
100
- words = reduced;
101
- changed = true;
102
- }
103
-
104
- // A copy of a register onto itself is nothing at all — and it is not something the dead-code
105
- // pass can see, because the lanes it writes are live; they were simply already correct.
106
- if (vm_decode_op(words[0]) === VM_OP.MOV && words[1] === words[2]) {
107
- changed = true;
108
- } else {
109
- out.push(words);
110
- }
111
-
112
- values.publish(words);
113
- }
114
-
115
- return changed ? out : null;
116
- }
117
-
118
- /**
119
- * @returns {number[]|null} the instruction with this read redirected, or `null` to leave it
120
- */
121
- function redirect(words, read, values) {
122
- const base = values.origin_of(read.base, read.span);
123
-
124
- if (base < 0 || base === read.base) {
125
- return null;
126
- }
127
-
128
- const candidate = words.slice();
129
-
130
- candidate[read.operand < 0 ? 1 : 2 + read.operand] = base;
131
-
132
- // Moving one operand changes how it sits against the others, and two runs of an instruction may
133
- // name the same slots or none of the same ones.
134
- return particle_instruction_is_well_formed(candidate) ? candidate : null;
135
- }
136
-
137
- /**
138
- * An identity `SWIZZLE` is a `MOV`, and a `MOV` whose destination is its source is nothing.
139
- *
140
- * @returns {number[]|null} the reduced instruction, `null` if there is nothing to reduce
141
- */
142
- function reduce_copy(words, instruction) {
143
- const op = instruction.op;
144
-
145
- if (op === VM_OP.SWIZZLE) {
146
- for (let lane = 0; lane < instruction.operation_width; lane++) {
147
- if (((words[3] >> (2 * lane)) & 3) !== lane) {
148
- return null;
149
- }
150
- }
151
-
152
- const candidate = [vm_encode_word0(VM_OP.MOV, instruction.width), words[1], words[2], 0, 0];
153
-
154
- return particle_instruction_is_well_formed(candidate) ? candidate : null;
155
- }
156
-
157
- return null;
158
- }
159
-
160
- /**
161
- * Have the producer write where its copy was going.
162
- *
163
- * Applied one at a time and re-derived, because a forward changes what the next one is looking at:
164
- * a chain of copies collapses from the far end, and the analysis it needs is cheap enough that
165
- * keeping it incrementally honest would cost more than redoing it.
166
- *
167
- * @param {number[][]} instructions
168
- * @returns {number[][]|null}
169
- */
170
- function forward_destinations(instructions) {
171
- let current = instructions;
172
- let changed = false;
173
-
174
- for (let attempt = 0; attempt < instructions.length; attempt++) {
175
- const next = forward_one_destination(current);
176
-
177
- if (next === null) {
178
- break;
179
- }
180
-
181
- current = next;
182
- changed = true;
183
- }
184
-
185
- return changed ? current : null;
186
- }
187
-
188
- /**
189
- * @param {number[][]} instructions
190
- * @returns {number[][]|null}
191
- */
192
- function forward_one_destination(instructions) {
193
- const decoded = decode_particle_instructions(instructions);
194
-
195
- for (let copy = 0; copy < decoded.length; copy++) {
196
- const move = decoded[copy];
197
-
198
- if (move.op !== VM_OP.MOV) {
199
- continue;
200
- }
201
-
202
- const destination = move.write.base;
203
- const source = move.reads[0].base;
204
- const span = move.write.span;
205
-
206
- if (destination === source) {
207
- continue;
208
- }
209
-
210
- const producer = sole_producer(decoded, copy, source, span);
211
-
212
- if (producer < 0
213
- || particle_run_is_touched_between(decoded, producer + 1, copy, destination, span)
214
- || !particle_run_is_dead_after(decoded, copy, source, span)) {
215
- continue;
216
- }
217
-
218
- const words = decoded[producer].words.slice();
219
-
220
- words[1] = destination;
221
-
222
- if (!particle_instruction_is_well_formed(words)) {
223
- continue;
224
- }
225
-
226
- const out = instructions.slice();
227
-
228
- out[producer] = words;
229
- out.splice(copy, 1);
230
-
231
- return out;
232
- }
233
-
234
- return null;
235
- }
236
-
237
- /**
238
- * The one instruction that put the value in `[base, base + span)`, if it is the only writer, wrote
239
- * exactly that run, and nothing between it and `copy` read it.
240
- *
241
- * @returns {number} instruction index, or `-1`
242
- */
243
- function sole_producer(decoded, copy, base, span) {
244
- for (let i = copy - 1; i >= 0; i--) {
245
- const instruction = decoded[i];
246
-
247
- // A HALT in between means the copy never runs; that is the dead-code pass's to sort out.
248
- if (instruction.op === VM_OP.HALT) {
249
- return -1;
250
- }
251
-
252
- // The write is checked first so a producer that reads the run it writes — `SIN r0, r0`, the
253
- // in-place form the register allocator reaches for constantly — is recognised as the
254
- // producer rather than rejected as an intervening reader of its own result.
255
- if (instruction.write !== null
256
- && particle_runs_overlap(instruction.write.base, instruction.write.span, base, span)) {
257
- return instruction.write.base === base && instruction.write.span === span ? i : -1;
258
- }
259
-
260
- for (const read of instruction.reads) {
261
- if (particle_runs_overlap(read.base, read.span, base, span)) {
262
- return -1;
263
- }
264
- }
265
- }
266
-
267
- return -1;
268
- }
1
+ import { VM_KIND, VM_OP, vm_operand_with_base, vm_register, vm_repack_instruction, vm_with_dst } from "../isa/ParticleVMISA.js";
2
+ import {
3
+ ParticleValueNumbering,
4
+ decode_particle_instructions,
5
+ particle_instruction_is_well_formed,
6
+ particle_read_slots,
7
+ particle_run_is_dead_after,
8
+ particle_runs_overlap,
9
+ } from "./particle_program_analysis.js";
10
+
11
+ /** @type {string} */
12
+ export const PARTICLE_PASS_PROPAGATE_COPIES = "propagate_copies";
13
+
14
+ /**
15
+ * Get rid of copies — by reading past them where the original is still intact, and by having the
16
+ * instruction that produced the value write where the copy was going.
17
+ *
18
+ * Copies are most of what a broadcast is. The node compiler widens a scalar with a `MOV` through
19
+ * `.xxxx` because some consumer asked for four lanes; when the consumer can read the scalar through
20
+ * that same swizzle, the copy is a register renaming and nothing else.
21
+ *
22
+ * ## Reading past a copy
23
+ *
24
+ * Every write gives its lanes a fresh value number and records the slot the value was ORIGINALLY
25
+ * computed in; a copy inherits both, through whatever swizzle it read its source with. A read can
26
+ * then be redirected to where its lanes' values live, as long as the originals still hold them —
27
+ * which is exactly "the value numbers still match", so a slot overwritten since fails the test rather
28
+ * than needing a separate invalidation. The redirected operand names the homes through a swizzle of
29
+ * its own, so a permutation, a broadcast and a plain copy are all read through alike: `MUL r0, r1,
30
+ * r2` where r2 is `r5.xxxx` becomes `MUL r0, r1, r5.xxxx`, and the broadcast is then dead.
31
+ *
32
+ * ## Writing where the copy was going
33
+ *
34
+ * `MOV d, s` where `s` was produced by one instruction, read by nothing but this copy, and dead
35
+ * afterwards is that instruction writing to the wrong register. Retargeting it and dropping the copy
36
+ * is what turns the graph compiler's broadcast-and-select into the two-lane value hand-written
37
+ * assembly would have built directly.
38
+ *
39
+ * The conditions are the obvious ones and all of them are checked: nothing between the producer and
40
+ * the copy may read the source or touch the destination, and nothing after may read the source.
41
+ * Retargeting a `RANDOM` is allowed — where its result lands is not part of the draw sequence.
42
+ *
43
+ * ## Copies spelled as something else
44
+ *
45
+ * A lane picked out of a vector — `MOV.1 r4, r0.y` — is the run at `r1`, and the assembler spells
46
+ * every operand canonically, so the pass never sees the difference. What is left to reduce here is
47
+ * a `MOV` of a register onto itself, which is nothing at all.
48
+ *
49
+ * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
50
+ */
51
+ export function pass_propagate_copies(instructions, context) {
52
+ const rounds = context.max_iterations ?? 3;
53
+
54
+ let current = instructions;
55
+ let changed = false;
56
+
57
+ for (let round = 0; round < rounds; round++) {
58
+ const redirected = redirect_reads(current, context);
59
+ const forwarded = forward_destinations(redirected ?? current);
60
+
61
+ if (redirected === null && forwarded === null) {
62
+ break;
63
+ }
64
+
65
+ current = forwarded ?? redirected;
66
+ changed = true;
67
+ }
68
+
69
+ return changed ? current : null;
70
+ }
71
+
72
+ /**
73
+ * Rewrite reads to name the slots their values were first computed in, and drop a `MOV` of a
74
+ * register onto itself.
75
+ *
76
+ * @param {number[][]} instructions
77
+ * @param {object} context
78
+ * @returns {number[][]|null}
79
+ */
80
+ function redirect_reads(instructions, context) {
81
+ const decoded = decode_particle_instructions(instructions);
82
+ const values = new ParticleValueNumbering(context.register_slots);
83
+
84
+ /** @type {number[][]} */
85
+ const out = [];
86
+
87
+ let changed = false;
88
+
89
+ for (const instruction of decoded) {
90
+ let words = instruction.words;
91
+
92
+ for (const read of instruction.reads) {
93
+ const candidate = redirect(words, read, values);
94
+
95
+ if (candidate !== null) {
96
+ words = candidate;
97
+ changed = true;
98
+ }
99
+ }
100
+
101
+ // A copy of a register onto itself is nothing at all — and it is not something the dead-code
102
+ // pass can see, because the lanes it writes are live; they were simply already correct.
103
+ if (is_copy_onto_itself(words, instruction)) {
104
+ changed = true;
105
+ } else {
106
+ out.push(words);
107
+ }
108
+
109
+ values.publish(words);
110
+ }
111
+
112
+ return changed ? out : null;
113
+ }
114
+
115
+ /**
116
+ * @param {number[]} words the instruction as it stands after redirection
117
+ * @param {import("./particle_program_analysis.js").ParticleDecodedInstruction} instruction
118
+ * @returns {boolean} whether it is a `MOV` reading its own destination run as it lies
119
+ */
120
+ function is_copy_onto_itself(words, instruction) {
121
+ return instruction.op === VM_OP.MOV
122
+ && instruction.sources[0].kind === VM_KIND.REG
123
+ && words[1] === vm_register(instruction.dst);
124
+ }
125
+
126
+ /**
127
+ * @returns {number[]|null} the instruction with this read redirected, or `null` to leave it
128
+ */
129
+ function redirect(words, read, values) {
130
+ const origin = values.origin_of_read(read);
131
+
132
+ if (origin < 0) {
133
+ return null;
134
+ }
135
+
136
+ const candidate = words.slice();
137
+
138
+ candidate[1 + read.operand] = origin;
139
+
140
+ const repacked = vm_repack_instruction(candidate);
141
+
142
+ if (repacked[1 + read.operand] === words[1 + read.operand]) {
143
+ return null;
144
+ }
145
+
146
+ return particle_instruction_is_well_formed(repacked) ? repacked : null;
147
+ }
148
+
149
+ /**
150
+ * Have the producer write where its copy was going.
151
+ *
152
+ * Applied one at a time and re-derived, because a forward changes what the next one is looking at:
153
+ * a chain of copies collapses from the far end, and the analysis it needs is cheap enough that
154
+ * keeping it incrementally honest would cost more than redoing it.
155
+ *
156
+ * @param {number[][]} instructions
157
+ * @returns {number[][]|null}
158
+ */
159
+ function forward_destinations(instructions) {
160
+ let current = instructions;
161
+ let changed = false;
162
+
163
+ for (let attempt = 0; attempt < instructions.length; attempt++) {
164
+ const next = forward_one_destination(current);
165
+
166
+ if (next === null) {
167
+ break;
168
+ }
169
+
170
+ current = next;
171
+ changed = true;
172
+ }
173
+
174
+ return changed ? current : null;
175
+ }
176
+
177
+ /**
178
+ * @param {number[][]} instructions
179
+ * @returns {number[][]|null}
180
+ */
181
+ function forward_one_destination(instructions) {
182
+ const decoded = decode_particle_instructions(instructions);
183
+
184
+ for (let copy = 0; copy < decoded.length; copy++) {
185
+ const move = decoded[copy];
186
+
187
+ // Only a plain copy of a register run has producers to retarget: a swizzled one reorders
188
+ // lanes the producers computed in order, and a MOV from a literal is a load, which the
189
+ // inlining pass deals with.
190
+ if (move.op !== VM_OP.MOV || move.sources[0].kind !== VM_KIND.REG) {
191
+ continue;
192
+ }
193
+
194
+ const source = move.sources[0];
195
+
196
+ if (source.word !== vm_register(source.base)) {
197
+ continue;
198
+ }
199
+
200
+ const destination = move.write.base;
201
+ const span = move.write.span;
202
+
203
+ // Overlapping runs would have the producers shift into each other's lanes; a copy of that
204
+ // shape is what a swizzle is for, and not worth the bookkeeping.
205
+ if (particle_runs_overlap(destination, span, source.base, span)) {
206
+ continue;
207
+ }
208
+
209
+ const plan = plan_forwarding(decoded, copy, source.base, span, destination);
210
+
211
+ if (plan === null) {
212
+ continue;
213
+ }
214
+
215
+ const out = instructions.slice();
216
+
217
+ for (const [index, words] of plan) {
218
+ out[index] = words;
219
+ }
220
+
221
+ out.splice(copy, 1);
222
+
223
+ return out;
224
+ }
225
+
226
+ return null;
227
+ }
228
+
229
+ /**
230
+ * How to have the producers of `[base, base + span)` write into `[destination, ...)` instead, so the
231
+ * copy at `copy` can go.
232
+ *
233
+ * Each lane has a producer — the last write to it before the copy — and every producer has to write
234
+ * within the run, so that moving it by `destination - base` moves lanes and nothing else. From the
235
+ * earliest producer to the copy, nothing may touch the destination: not a write, since the value is
236
+ * now being built there, and not a read, since what it read was the destination's old contents. A
237
+ * read of the source in that gap is a read of the value on its way to the copy and follows it to the
238
+ * destination — unless it comes before the producer of a lane it reads, in which case it wanted what
239
+ * the slot held before and stays as it is. A read that is half one and half the other is left
240
+ * alone, and so is the whole copy. After the copy, the source has to be dead.
241
+ *
242
+ * @param {import("./particle_program_analysis.js").ParticleDecodedInstruction[]} decoded
243
+ * @param {number} copy index of the `MOV`
244
+ * @param {number} base first slot of the source run
245
+ * @param {number} span
246
+ * @param {number} destination first slot of the destination run
247
+ * @returns {Array<[number, number[]]>|null} rewritten instructions by index, or `null` to leave the copy
248
+ */
249
+ function plan_forwarding(decoded, copy, base, span, destination) {
250
+ /** @type {Int32Array} per lane, the instruction that produced it; `-1` until found */
251
+ const producer = new Int32Array(span).fill(-1);
252
+
253
+ let unproduced = span;
254
+
255
+ for (let i = copy - 1; i >= 0 && unproduced > 0; i--) {
256
+ const instruction = decoded[i];
257
+
258
+ // A HALT in between means the copy never runs; that is the dead-code pass's to sort out.
259
+ if (instruction.op === VM_OP.HALT) {
260
+ return null;
261
+ }
262
+
263
+ const write = instruction.write;
264
+
265
+ if (write === null || !particle_runs_overlap(write.base, write.span, base, span)) {
266
+ continue;
267
+ }
268
+
269
+ if (write.base < base || write.base + write.span > base + span) {
270
+ return null;
271
+ }
272
+
273
+ for (let lane = write.base - base; lane < write.base - base + write.span; lane++) {
274
+ if (producer[lane] < 0) {
275
+ producer[lane] = i;
276
+ unproduced--;
277
+ }
278
+ }
279
+ }
280
+
281
+ if (unproduced > 0) {
282
+ return null;
283
+ }
284
+
285
+ const earliest = Math.min(...producer);
286
+
287
+ /** @type {Map<number, number[]>} instruction index -> its rewritten words */
288
+ const rewritten = new Map();
289
+
290
+ const words_of = (index) => {
291
+ if (!rewritten.has(index)) {
292
+ rewritten.set(index, decoded[index].words.slice());
293
+ }
294
+
295
+ return rewritten.get(index);
296
+ };
297
+
298
+ for (let i = earliest + 1; i < copy; i++) {
299
+ const instruction = decoded[i];
300
+
301
+ if (instruction.op === VM_OP.HALT) {
302
+ return null;
303
+ }
304
+
305
+ if (instruction.write !== null
306
+ && particle_runs_overlap(instruction.write.base, instruction.write.span, destination, span)) {
307
+ return null;
308
+ }
309
+
310
+ for (const read of instruction.reads) {
311
+ if (particle_runs_overlap(read.base, read.span, destination, span)) {
312
+ return null;
313
+ }
314
+
315
+ const slots = particle_read_slots(read);
316
+ const inside = slots.filter(slot => slot >= base && slot < base + span);
317
+
318
+ if (inside.length === 0) {
319
+ continue;
320
+ }
321
+
322
+ if (inside.length !== slots.length) {
323
+ return null;
324
+ }
325
+
326
+ const produced = slots.filter(slot => producer[slot - base] < i).length;
327
+
328
+ if (produced === 0) {
329
+ continue;
330
+ }
331
+
332
+ if (produced !== slots.length) {
333
+ return null;
334
+ }
335
+
336
+ words_of(i)[1 + read.operand] = vm_operand_with_base(read.word, read.base - base + destination);
337
+ }
338
+ }
339
+
340
+ if (!particle_run_is_dead_after(decoded, copy, base, span)) {
341
+ return null;
342
+ }
343
+
344
+ for (const index of new Set(producer)) {
345
+ const words = words_of(index);
346
+
347
+ words[0] = vm_with_dst(words[0], decoded[index].write.base - base + destination);
348
+ }
349
+
350
+ const plan = [];
351
+
352
+ for (const [index, words] of rewritten) {
353
+ if (!particle_instruction_is_well_formed(words)) {
354
+ return null;
355
+ }
356
+
357
+ plan.push([index, words]);
358
+ }
359
+
360
+ return plan;
361
+ }
@@ -0,0 +1,4 @@
1
+ export function pass_schedule(instructions: number[][], context: import("./optimize_particle_program.js").ParticleOptimizerContext): number[][];
2
+ /** @type {string} */
3
+ export const PARTICLE_PASS_SCHEDULE: string;
4
+ //# sourceMappingURL=pass_schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pass_schedule.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_schedule.js"],"names":[],"mappings":"AAmHsD,gJAWoB;AA5H1E,qBAAqB;AACrB,qCADW,MAAM,CACgC"}