@woosh/meep-engine 3.16.0 → 3.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (410) hide show
  1. package/editor/particles/effect/ParticleEffectDocument.d.ts +21 -6
  2. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  3. package/editor/particles/effect/ParticleEffectDocument.js +38 -17
  4. package/editor/view/node-graph/NodeGraphClipboard.d.ts +186 -0
  5. package/editor/view/node-graph/NodeGraphClipboard.d.ts.map +1 -0
  6. package/editor/view/node-graph/NodeGraphClipboard.js +231 -0
  7. package/editor/view/node-graph/NodeGraphEditorView.d.ts +59 -1
  8. package/editor/view/node-graph/NodeGraphEditorView.d.ts.map +1 -1
  9. package/editor/view/node-graph/NodeGraphEditorView.js +248 -5
  10. package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
  11. package/editor/view/node-graph/NodeGraphView.js +84 -8
  12. package/editor/view/node-graph/actions/connection_bind_actions.d.ts +23 -0
  13. package/editor/view/node-graph/actions/connection_bind_actions.d.ts.map +1 -0
  14. package/editor/view/node-graph/actions/connection_bind_actions.js +39 -0
  15. package/editor/view/particles/effect/ParticleCodeEditorView.d.ts.map +1 -1
  16. package/editor/view/particles/effect/ParticleCodeEditorView.js +4 -3
  17. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts +20 -0
  18. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -0
  19. package/editor/view/particles/effect/ParticleCurveEditorView.js +574 -0
  20. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
  21. package/editor/view/particles/effect/ParticleEmitterInspectorView.js +27 -1
  22. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts +24 -0
  23. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -0
  24. package/editor/view/particles/effect/ParticleGradientEditorView.js +472 -0
  25. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts +5 -0
  26. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts.map +1 -1
  27. package/editor/view/particles/effect/ParticleGraphEditorView.js +61 -31
  28. package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
  29. package/editor/view/particles/effect/ParticleNodeParametersView.js +33 -0
  30. package/editor/view/particles/effect/particle-editor.css +123 -35
  31. package/package.json +1 -1
  32. package/src/core/binary/allocator/OffsetAllocator.d.ts +25 -16
  33. package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
  34. package/src/core/binary/allocator/OffsetAllocator.js +10 -1
  35. package/src/core/collection/array/typed/float32_array_hash.d.ts +21 -0
  36. package/src/core/collection/array/typed/float32_array_hash.d.ts.map +1 -0
  37. package/src/core/collection/array/typed/float32_array_hash.js +38 -0
  38. package/src/core/graph/csr/CSRGraph.d.ts +8 -1
  39. package/src/core/graph/csr/CSRGraph.d.ts.map +1 -1
  40. package/src/core/graph/csr/CSRGraph.js +14 -6
  41. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts +24 -0
  42. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts.map +1 -1
  43. package/src/core/model/node-graph/visual/layout/LayoutProblem.js +27 -0
  44. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +26 -0
  45. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
  46. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +28 -0
  47. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts +92 -3
  48. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts.map +1 -1
  49. package/src/core/model/node-graph/visual/layout/RouteGrid.js +405 -242
  50. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts +50 -5
  51. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts.map +1 -1
  52. package/src/core/model/node-graph/visual/layout/RouteSearch.js +160 -24
  53. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts +7 -0
  54. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts.map +1 -1
  55. package/src/core/model/node-graph/visual/layout/RouteSet.js +8 -0
  56. package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +9 -3
  57. package/src/core/model/node-graph/visual/layout/layout_build_problem.d.ts.map +1 -1
  58. package/src/core/model/node-graph/visual/layout/layout_build_problem.js +7 -0
  59. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts +9 -3
  60. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +1 -1
  61. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.js +17 -3
  62. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts +9 -6
  63. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts.map +1 -1
  64. package/src/core/model/node-graph/visual/layout/layout_node_graph.js +49 -7
  65. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts +11 -1
  66. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +1 -1
  67. package/src/core/model/node-graph/visual/layout/layout_order_layers.js +135 -16
  68. package/src/core/model/node-graph/visual/layout/route_connections.d.ts +29 -0
  69. package/src/core/model/node-graph/visual/layout/route_connections.d.ts.map +1 -1
  70. package/src/core/model/node-graph/visual/layout/route_connections.js +716 -309
  71. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts +3 -2
  72. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts.map +1 -1
  73. package/src/core/model/node-graph/visual/layout/route_grid_build.js +7 -15
  74. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts +6 -0
  75. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts.map +1 -1
  76. package/src/core/model/node-graph/visual/layout/route_nudge.js +42 -13
  77. package/src/engine/animation/AnimationUtils.js +246 -246
  78. package/src/engine/animation/Animations.js +74 -74
  79. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2078 -2078
  80. package/src/engine/ecs/EventType.d.ts +0 -1
  81. package/src/engine/ecs/EventType.js +1 -26
  82. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +1 -1
  83. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +1 -1
  84. package/src/engine/ecs/ik/ik_write_local_rotation.js +3 -7
  85. package/src/engine/ecs/parent/EntityNode.d.ts.map +1 -1
  86. package/src/engine/ecs/parent/EntityNode.js +4 -9
  87. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
  88. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +360 -364
  89. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts +41 -0
  90. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts.map +1 -0
  91. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.js +40 -0
  92. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +8 -0
  93. package/src/engine/ecs/transform/t64_announce_change.d.ts +10 -7
  94. package/src/engine/ecs/transform/t64_announce_change.d.ts.map +1 -1
  95. package/src/engine/ecs/transform/t64_announce_change.js +12 -12
  96. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts +30 -0
  97. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts.map +1 -0
  98. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js +29 -0
  99. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
  100. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +13 -21
  101. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
  102. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +4 -8
  103. package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
  104. package/src/engine/graphics3/LightSystem.js +4 -8
  105. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  106. package/src/engine/graphics3/MeshSystem.js +9 -19
  107. package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -1
  108. package/src/engine/graphics3/ParticleEmitterSystem.js +4 -8
  109. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  110. package/src/engine/graphics3/ShadedGeometrySystem.js +4 -10
  111. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts +1 -1
  112. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts.map +1 -1
  113. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +4 -8
  114. package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.js +218 -218
  115. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  116. package/src/engine/physics/ecs/PhysicsSystem.js +2 -5
  117. package/src/engine/sound/ecs/SoundListenerSystem.d.ts.map +1 -1
  118. package/src/engine/sound/ecs/SoundListenerSystem.js +6 -8
  119. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts +0 -4
  120. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts.map +1 -1
  121. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +5 -11
  122. package/src/shade/playground/particle_editor/README.md +43 -2
  123. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  124. package/src/shade/playground/particle_system/particle_prototype.js +4 -5
  125. package/src/shade/playground/particle_system/particle_scene.js +4 -4
  126. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  127. package/src/shade/renderer/Renderer.js +13 -1
  128. package/src/shade/renderer/particles/DESIGN.md +104 -19
  129. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +64 -50
  130. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  131. package/src/shade/renderer/particles/GPUParticleSystem.js +176 -78
  132. package/src/shade/renderer/particles/ParticleConstants.d.ts +59 -23
  133. package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
  134. package/src/shade/renderer/particles/ParticleConstants.js +66 -23
  135. package/src/shade/renderer/particles/ParticleRenderMode.d.ts +19 -0
  136. package/src/shade/renderer/particles/ParticleRenderMode.d.ts.map +1 -0
  137. package/src/shade/renderer/particles/ParticleRenderMode.js +33 -0
  138. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  139. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +167 -166
  140. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts +37 -0
  141. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -0
  142. package/src/shade/renderer/particles/data/particle_emitter_record.js +109 -0
  143. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +3 -3
  144. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +303 -303
  145. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +18 -0
  146. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -1
  147. package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +152 -133
  148. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +0 -11
  149. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
  150. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +720 -621
  151. package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
  152. package/src/shade/renderer/particles/graph/compile_particle_graph.js +8 -3
  153. package/src/shade/renderer/particles/graph/flatten_particle_graph.d.ts.map +1 -1
  154. package/src/shade/renderer/particles/graph/flatten_particle_graph.js +244 -213
  155. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
  156. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +6 -0
  157. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
  158. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +294 -319
  159. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.d.ts.map +1 -1
  160. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.js +524 -517
  161. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts +22 -0
  162. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts.map +1 -0
  163. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.js +517 -0
  164. package/src/shade/renderer/particles/graph/groups/simplex_reference.d.ts.map +1 -1
  165. package/src/shade/renderer/particles/graph/groups/simplex_reference.js +185 -159
  166. package/src/shade/renderer/particles/graph/make_particle_group.d.ts.map +1 -1
  167. package/src/shade/renderer/particles/graph/make_particle_group.js +2 -20
  168. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts +17 -0
  169. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts.map +1 -0
  170. package/src/shade/renderer/particles/graph/particle_compare_ops.js +22 -0
  171. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts +28 -8
  172. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts.map +1 -1
  173. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.js +49 -25
  174. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +40 -0
  175. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
  176. package/src/shade/renderer/particles/graph/particle_node_parameters.js +312 -234
  177. package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
  178. package/src/shade/renderer/particles/graph/particle_node_presentation.js +59 -3
  179. package/src/shade/renderer/particles/graph/particle_ramp.d.ts +230 -0
  180. package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -0
  181. package/src/shade/renderer/particles/graph/particle_ramp.js +403 -0
  182. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts +7 -1
  183. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts.map +1 -1
  184. package/src/shade/renderer/particles/graph/validate_particle_graph.js +66 -10
  185. package/src/shade/renderer/particles/graph_particles.d.ts +23 -69
  186. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  187. package/src/shade/renderer/particles/graph_particles.js +105 -262
  188. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  189. package/src/shade/renderer/particles/graph_particles_avboit.js +3 -2
  190. package/src/shade/renderer/particles/graph_particles_billboard.d.ts +37 -0
  191. package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +1 -0
  192. package/src/shade/renderer/particles/graph_particles_billboard.js +93 -0
  193. package/src/shade/renderer/particles/isa/InstructionStream.d.ts +51 -22
  194. package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
  195. package/src/shade/renderer/particles/isa/InstructionStream.js +98 -38
  196. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts +49 -8
  197. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts.map +1 -1
  198. package/src/shade/renderer/particles/isa/ParticleProgram.js +95 -150
  199. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +306 -64
  200. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
  201. package/src/shade/renderer/particles/isa/ParticleVMISA.js +505 -136
  202. package/src/shade/renderer/particles/isa/particle_assembly.d.ts +36 -12
  203. package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
  204. package/src/shade/renderer/particles/isa/particle_assembly.js +354 -139
  205. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts +9 -0
  206. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts.map +1 -0
  207. package/src/shade/renderer/particles/isa/validate_particle_program.js +128 -0
  208. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts +23 -0
  209. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
  210. package/src/shade/renderer/particles/layout/ParticleLayout.js +68 -0
  211. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts +77 -0
  212. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts.map +1 -0
  213. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.js +219 -0
  214. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts +83 -0
  215. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -0
  216. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +283 -0
  217. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +133 -0
  218. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts.map +1 -0
  219. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +334 -0
  220. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts +117 -0
  221. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts.map +1 -0
  222. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.js +70 -0
  223. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts +97 -0
  224. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts.map +1 -0
  225. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +462 -0
  226. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts +116 -0
  227. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts.map +1 -0
  228. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js +687 -0
  229. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts +57 -0
  230. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts.map +1 -0
  231. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +860 -0
  232. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts +115 -0
  233. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts.map +1 -0
  234. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.js +264 -0
  235. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +81 -42
  236. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
  237. package/src/shade/renderer/particles/optimizer/optimize_particle_program.js +477 -478
  238. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts +100 -0
  239. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts.map +1 -0
  240. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.js +236 -0
  241. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts +139 -59
  242. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
  243. package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +764 -647
  244. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts +40 -7
  245. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
  246. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +376 -213
  247. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts +30 -3
  248. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
  249. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +337 -223
  250. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +24 -38
  251. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
  252. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +166 -206
  253. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts +99 -0
  254. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts.map +1 -0
  255. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.js +313 -0
  256. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts +3 -2
  257. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts.map +1 -1
  258. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.js +198 -197
  259. package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.d.ts.map +1 -1
  260. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts +19 -0
  261. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
  262. package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +678 -561
  263. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts +22 -0
  264. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts.map +1 -0
  265. package/src/shade/renderer/particles/optimizer/pass_inline_constants.js +221 -0
  266. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.d.ts.map +1 -1
  267. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.js +63 -72
  268. package/src/shade/renderer/particles/optimizer/pass_pack_registers.d.ts.map +1 -1
  269. package/src/shade/renderer/particles/optimizer/pass_pack_registers.js +87 -86
  270. package/src/shade/renderer/particles/optimizer/pass_peephole.d.ts.map +1 -1
  271. package/src/shade/renderer/particles/optimizer/pass_peephole.js +392 -271
  272. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.d.ts.map +1 -1
  273. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.js +361 -268
  274. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts +4 -0
  275. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts.map +1 -0
  276. package/src/shade/renderer/particles/optimizer/pass_schedule.js +244 -0
  277. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.d.ts.map +1 -1
  278. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.js +154 -151
  279. package/src/shade/renderer/particles/particle_test_fixtures.d.ts +20 -0
  280. package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +1 -1
  281. package/src/shade/renderer/particles/particle_test_fixtures.js +229 -203
  282. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +99 -25
  283. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  284. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +438 -286
  285. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +109 -0
  286. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -0
  287. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +127 -0
  288. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +87 -102
  289. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  290. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +184 -163
  291. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts +26 -0
  292. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts.map +1 -1
  293. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts +130 -0
  294. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts.map +1 -0
  295. package/src/shade/renderer/particles/runtime/ProgramHeap.js +595 -0
  296. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts +91 -0
  297. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts.map +1 -0
  298. package/src/shade/renderer/particles/runtime/ProgramPlacement.js +106 -0
  299. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +5 -2
  300. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
  301. package/src/shade/renderer/particles/runtime/create_particle_effect.js +22 -19
  302. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts +28 -0
  303. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts.map +1 -0
  304. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.js +136 -0
  305. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts +35 -0
  306. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts.map +1 -0
  307. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.js +133 -0
  308. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts +18 -9
  309. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  310. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +20 -80
  311. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts +33 -0
  312. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -0
  313. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +114 -0
  314. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts +8 -0
  315. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  316. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +33 -101
  317. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts +45 -0
  318. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -0
  319. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +123 -0
  320. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +51 -0
  321. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +1 -0
  322. package/src/shade/renderer/particles/sort/graph_particle_sort.js +120 -0
  323. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts +6 -0
  324. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts.map +1 -0
  325. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.js +16 -0
  326. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +4 -1
  327. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  328. package/src/shade/renderer/particles/vm/ParticleVMReference.js +261 -140
  329. package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
  330. package/src/shade/renderer/particles/vm/chunk_particle_vm.js +217 -255
  331. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts +43 -0
  332. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts.map +1 -0
  333. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.js +55 -0
  334. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts +62 -0
  335. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts.map +1 -0
  336. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.js +86 -0
  337. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts +22 -0
  338. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts.map +1 -0
  339. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.js +32 -0
  340. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts +9 -0
  341. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts.map +1 -0
  342. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.js +19 -0
  343. package/src/shade/renderer/shader/chunk/noise/psrdnoise/README.md +65 -0
  344. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts +24 -0
  345. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts.map +1 -0
  346. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.js +83 -0
  347. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts +25 -0
  348. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts.map +1 -0
  349. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.js +42 -0
  350. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts +31 -0
  351. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts.map +1 -0
  352. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.js +80 -0
  353. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts +26 -0
  354. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts.map +1 -0
  355. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.js +109 -0
  356. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts +38 -0
  357. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts.map +1 -0
  358. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.js +129 -0
  359. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts +21 -0
  360. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts.map +1 -0
  361. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.js +35 -0
  362. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts +19 -0
  363. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts.map +1 -0
  364. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.js +28 -0
  365. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts +13 -0
  366. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts.map +1 -0
  367. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.js +22 -0
  368. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts +22 -0
  369. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts.map +1 -0
  370. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.js +59 -0
  371. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts +23 -0
  372. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts.map +1 -0
  373. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.js +74 -0
  374. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts +34 -1
  375. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts.map +1 -1
  376. package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +41 -1
  377. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +3 -2
  378. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  379. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +49 -10
  380. package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
  381. package/src/view/minimap/dom/MinimapCameraView.js +4 -9
  382. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts +0 -15
  383. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts.map +0 -1
  384. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts +0 -45
  385. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts.map +0 -1
  386. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts +0 -24
  387. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts.map +0 -1
  388. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts +0 -19
  389. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts.map +0 -1
  390. package/src/engine/ecs/transform/__probe.d.ts +0 -4
  391. package/src/engine/ecs/transform/__probe.d.ts.map +0 -1
  392. package/src/engine/ecs/util/hideEntityGracefully.d.ts +0 -9
  393. package/src/engine/ecs/util/hideEntityGracefully.d.ts.map +0 -1
  394. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts +0 -27
  395. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts.map +0 -1
  396. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts +0 -14
  397. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +0 -1
  398. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts +0 -156
  399. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts.map +0 -1
  400. package/src/shade/renderer/particles/runtime/Emitter.d.ts +0 -219
  401. package/src/shade/renderer/particles/runtime/Emitter.d.ts.map +0 -1
  402. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts +0 -77
  403. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts.map +0 -1
  404. package/src/shade/renderer/particles/runtime/ProgramArena.js +0 -155
  405. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts +0 -15
  406. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts.map +0 -1
  407. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts +0 -34
  408. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts.map +0 -1
  409. package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts +0 -32
  410. package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts.map +0 -1
@@ -0,0 +1,22 @@
1
+ export function pass_inline_constants(instructions: number[][], context: import("./optimize_particle_program.js").ParticleOptimizerContext): number[][];
2
+ /** @type {string} */
3
+ export const PARTICLE_PASS_INLINE_CONSTANTS: string;
4
+ export type ParticleConstantSource = {
5
+ /**
6
+ * first register slot the constant is written to
7
+ */
8
+ base: number;
9
+ /**
10
+ * slots it fills
11
+ */
12
+ span: number;
13
+ /**
14
+ * the `f32` bit pattern each slot receives
15
+ */
16
+ bits: Uint32Array;
17
+ /**
18
+ * whether every slot receives the same bits
19
+ */
20
+ uniform: boolean;
21
+ };
22
+ //# sourceMappingURL=pass_inline_constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pass_inline_constants.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_inline_constants.js"],"names":[],"mappings":"AAmHY,wJAUZ;AArHA,qBAAqB;AACrB,6CADW,MAAM,CACgD;;;;;UA0FnD,MAAM;;;;UACN,MAAM;;;;UACN,WAAW;;;;aACX,OAAO"}
@@ -0,0 +1,221 @@
1
+ import { VM_KIND, VM_OP, vm_f32_bits, vm_pack_instruction, vm_with_kind } from "../isa/ParticleVMISA.js";
2
+ import {
3
+ decode_particle_instruction,
4
+ decode_particle_instructions,
5
+ particle_instruction_is_well_formed,
6
+ particle_read_slots,
7
+ } from "./particle_program_analysis.js";
8
+
9
+ /** @type {string} */
10
+ export const PARTICLE_PASS_INLINE_CONSTANTS = "inline_constants";
11
+
12
+ /**
13
+ * Move constants out of the register file and into the instructions that read them.
14
+ *
15
+ * `LOAD_CONST r, c` puts a value that never changes into a register, so that the next instruction
16
+ * can read a register — which was the only thing an instruction could read, until a source could be
17
+ * a literal (see the operand kinds in {@link ../isa/ParticleVMISA.js}). Now the load is a detour:
18
+ * the consumer can name the value itself. This pass finds every instruction that reads the loaded
19
+ * run before anything overwrites it, rewrites that operand to carry the constant, and deletes the
20
+ * load. A constant read by many instructions is inlined into each of them; unlike a register, a
21
+ * literal costs nothing to repeat.
22
+ *
23
+ * A literal is one value in every lane, so a consumer takes it only where every lane it reads holds
24
+ * the same `f32` — every scalar, every lane-uniform vector, and every swizzle whose selected lanes
25
+ * happen to agree. A vector whose lanes differ keeps its load: the pool is where such a value lives.
26
+ *
27
+ * A load whose value is uniform but that cannot be inlined — a consumer reads past the run, or
28
+ * reads a lane something in between has overwritten — keeps its register, but not its opcode: it
29
+ * becomes a `MOV` from the literal, so that the only `LOAD_CONST`s left in a program this pass has
30
+ * been over are the ones the pool exists for.
31
+ *
32
+ * ## What must not change
33
+ *
34
+ * The rewrite is bit-exact: a literal is the `f32` bits the pool word held, and the interpreters
35
+ * fetch it through the same resolver they fetch a register with. The other passes do not have to
36
+ * know this one exists — a literal is not a register run, so liveness, aliasing and copy propagation
37
+ * see through it by construction — and it is idempotent: a program with nothing left to inline
38
+ * comes back as `null`.
39
+ *
40
+ * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
41
+ */
42
+ export function pass_inline_constants(instructions, context) {
43
+ const constants = context.constants;
44
+
45
+ if (constants === undefined || constants.length === 0) {
46
+ return null;
47
+ }
48
+
49
+ const decoded = decode_particle_instructions(instructions);
50
+ /** @type {number[][]} the stream being rewritten; `decoded` is kept in step with it */
51
+ const out = instructions.map(words => Array.from(words));
52
+ const removed = new Uint8Array(decoded.length);
53
+
54
+ let changed = false;
55
+
56
+ for (let i = 0; i < decoded.length; i++) {
57
+ const source = constant_source(decoded[i], constants);
58
+
59
+ if (source === null) {
60
+ continue;
61
+ }
62
+
63
+ const rewrites = plan_inlining(decoded, i, source);
64
+
65
+ if (rewrites !== null) {
66
+ for (const [index, words] of rewrites) {
67
+ out[index] = words;
68
+ decoded[index] = decode_particle_instruction(words, index);
69
+ }
70
+
71
+ removed[i] = 1;
72
+ changed = true;
73
+ continue;
74
+ }
75
+
76
+ // The value has to stay in a register, so the instruction stays — as a MOV from the literal,
77
+ // which is the same work under the opcode the interpreter already has for copies.
78
+ if (decoded[i].op === VM_OP.LOAD_CONST && source.uniform) {
79
+ const words = vm_pack_instruction(
80
+ VM_OP.MOV, decoded[i].width, decoded[i].dst,
81
+ [VM_KIND.IMM, VM_KIND.NONE, VM_KIND.NONE],
82
+ [source.bits[0], 0, 0]
83
+ );
84
+
85
+ out[i] = words;
86
+ decoded[i] = decode_particle_instruction(words, i);
87
+ changed = true;
88
+ }
89
+ }
90
+
91
+ if (!changed) {
92
+ return null;
93
+ }
94
+
95
+ return out.filter((words, index) => removed[index] === 0);
96
+ }
97
+
98
+ /**
99
+ * @typedef {object} ParticleConstantSource
100
+ * @property {number} base first register slot the constant is written to
101
+ * @property {number} span slots it fills
102
+ * @property {Uint32Array} bits the `f32` bit pattern each slot receives
103
+ * @property {boolean} uniform whether every slot receives the same bits
104
+ */
105
+
106
+ /**
107
+ * What an instruction writes into its destination when that is a constant: a `LOAD_CONST`, or a
108
+ * `MOV` from a literal. `null` for anything else.
109
+ *
110
+ * @param {import("./particle_program_analysis.js").ParticleDecodedInstruction} instruction
111
+ * @param {ArrayLike<number>} constants
112
+ * @returns {ParticleConstantSource|null}
113
+ */
114
+ function constant_source(instruction, constants) {
115
+ if (instruction.write === null) {
116
+ return null;
117
+ }
118
+
119
+ const span = instruction.write.span;
120
+ const bits = new Uint32Array(span);
121
+
122
+ if (instruction.op === VM_OP.LOAD_CONST) {
123
+ const pool = instruction.words[1];
124
+
125
+ if (pool + span > constants.length) {
126
+ // Out of the pool: a malformed program, left for `validate` to name.
127
+ return null;
128
+ }
129
+
130
+ for (let lane = 0; lane < span; lane++) {
131
+ bits[lane] = vm_f32_bits(constants[pool + lane]);
132
+ }
133
+ } else if (instruction.op === VM_OP.MOV && instruction.sources[0].kind === VM_KIND.IMM) {
134
+ bits.fill(instruction.sources[0].word);
135
+ } else {
136
+ return null;
137
+ }
138
+
139
+ let uniform = true;
140
+
141
+ for (let lane = 1; lane < span; lane++) {
142
+ uniform = uniform && bits[lane] === bits[0];
143
+ }
144
+
145
+ return { base: instruction.write.base, span, bits, uniform };
146
+ }
147
+
148
+ /**
149
+ * Every consumer of the constant's run, rewritten to carry the constant — or `null` when one of
150
+ * them cannot.
151
+ *
152
+ * Walks forward from the load until every slot of the run has been overwritten or the section ends.
153
+ * Each register read that touches the run must lie entirely inside the slots the load still owns —
154
+ * a read reaching past it, or into a lane something has since overwritten, is reading a value the
155
+ * constant is not — and must see one value in every lane it reads.
156
+ *
157
+ * @param {import("./particle_program_analysis.js").ParticleDecodedInstruction[]} decoded
158
+ * @param {number} index of the load
159
+ * @param {ParticleConstantSource} source
160
+ * @returns {Map<number, number[]>|null} instruction index -> its rewritten words
161
+ */
162
+ function plan_inlining(decoded, index, source) {
163
+ /** slots of the run the load still owns */
164
+ const pending = new Set();
165
+
166
+ for (let lane = 0; lane < source.span; lane++) {
167
+ pending.add(source.base + lane);
168
+ }
169
+
170
+ /** @type {Map<number, number[]>} */
171
+ const rewrites = new Map();
172
+
173
+ for (let j = index + 1; j < decoded.length && pending.size > 0; j++) {
174
+ const instruction = decoded[j];
175
+
176
+ // Nothing past a HALT runs, so nothing past it consumes.
177
+ if (instruction.op === VM_OP.HALT) {
178
+ break;
179
+ }
180
+
181
+ for (const read of instruction.reads) {
182
+ const slots = particle_read_slots(read);
183
+
184
+ // A slot the run once held but something has since overwritten is not the constant any
185
+ // more, and a read of it is a read of that something. Only the slots still standing count.
186
+ if (!slots.some(slot => pending.has(slot))) {
187
+ continue;
188
+ }
189
+
190
+ // Touches the constant, so it has to be wholly the constant, and one value throughout.
191
+ if (!slots.every(slot => pending.has(slot))) {
192
+ return null;
193
+ }
194
+
195
+ const first = source.bits[slots[0] - source.base];
196
+
197
+ if (!slots.every(slot => source.bits[slot - source.base] === first)) {
198
+ return null;
199
+ }
200
+
201
+ const words = (rewrites.get(j) ?? instruction.words).slice();
202
+
203
+ words[0] = vm_with_kind(words[0], read.operand, VM_KIND.IMM);
204
+ words[1 + read.operand] = first;
205
+
206
+ if (!particle_instruction_is_well_formed(words)) {
207
+ return null;
208
+ }
209
+
210
+ rewrites.set(j, words);
211
+ }
212
+
213
+ if (instruction.write !== null) {
214
+ for (let lane = 0; lane < instruction.write.span; lane++) {
215
+ pending.delete(instruction.write.base + lane);
216
+ }
217
+ }
218
+ }
219
+
220
+ return rewrites;
221
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"pass_narrow_widths.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_narrow_widths.js"],"names":[],"mappings":"AAwEuB,qJAAiP;AAjExQ,qBAAqB;AACrB,0CADW,MAAM,CAC0C"}
1
+ {"version":3,"file":"pass_narrow_widths.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_narrow_widths.js"],"names":[],"mappings":"AA+DguE,qJAAqP;AAxDr9E,qBAAqB;AACrB,0CADW,MAAM,CAC0C"}
@@ -1,72 +1,63 @@
1
- import { VM_OP, vm_encode_word0 } from "../isa/ParticleVMISA.js";
2
- import {
3
- analyze_particle_lanes,
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_NARROW_WIDTHS = "narrow_widths";
10
-
11
- /**
12
- * Shrink each instruction to the lanes anything actually reads.
13
- *
14
- * Width is what stops every value costing four registers, and a lowering that works one value at a
15
- * time has no way to know how wide its consumer will turn out to be — the node compiler emits a
16
- * four-lane broadcast, learns later that one lane of it is read, and cannot go back. Reading the
17
- * finished stream backwards can: {@link analyze_particle_lanes} already knows the highest live lane
18
- * of every destination, and this pass writes that width into the instruction.
19
- *
20
- * The saving is in slots more often than in instructions. A narrowed value stops occupying the runs
21
- * above it, which is what lets the register-packing pass reclaim them, and the register file is the
22
- * interpreter's dominant cost — see the occupancy table in `vm/chunk_particle_vm.js`.
23
- *
24
- * Lanes are a run from zero, so the width follows the *highest* live lane rather than the count of
25
- * them: a live lane 2 holds the instruction at three lanes however dead lanes 0 and 1 are. Clearing
26
- * out a hole in the middle would mean splitting the instruction, which costs more than the lane.
27
- *
28
- * A `SWIZZLE` gets its pattern trimmed as well as its width, because a pattern's four selectors are
29
- * read whatever the instruction writes — an untrimmed one keeps the whole source value alive to feed
30
- * lanes that no longer exist.
31
- *
32
- * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
33
- */
34
- export function pass_narrow_widths(instructions, context) {
35
- const decoded = decode_particle_instructions(instructions);
36
- const { keep, width, pattern } = analyze_particle_lanes(decoded, context.register_slots);
37
-
38
- /** @type {number[][]} */
39
- const out = instructions.slice();
40
-
41
- let changed = false;
42
-
43
- for (let i = 0; i < instructions.length; i++) {
44
- const instruction = decoded[i];
45
-
46
- // Instructions nothing keeps are the dead-code pass's to remove, not this one's to narrow.
47
- if (!keep[i] || (width[i] === instruction.width && pattern[i] === instruction.words[3])) {
48
- continue;
49
- }
50
-
51
- const words = instruction.words.slice();
52
-
53
- words[0] = vm_encode_word0(instruction.op, width[i]);
54
-
55
- if (instruction.op === VM_OP.SWIZZLE) {
56
- words[3] = pattern[i];
57
- }
58
-
59
- // Narrowing moves no base and shrinks every run of an instruction together, so an exact
60
- // alias stays exact and disjoint runs stay disjoint — except a swizzle, whose source run
61
- // follows the pattern rather than the width. Rather than reason about which case this is,
62
- // ask; a rejected narrowing costs a lane, and an accepted illegal one costs correctness.
63
- if (!particle_instruction_is_well_formed(words)) {
64
- continue;
65
- }
66
-
67
- out[i] = words;
68
- changed = true;
69
- }
70
-
71
- return changed ? out : null;
72
- }
1
+ import { vm_with_width } from "../isa/ParticleVMISA.js";
2
+ import {
3
+ analyze_particle_lanes,
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_NARROW_WIDTHS = "narrow_widths";
10
+
11
+ /**
12
+ * Shrink each instruction to the lanes anything actually reads.
13
+ *
14
+ * Width is what stops every value costing four registers, and a lowering that works one value at a
15
+ * time has no way to know how wide its consumer will turn out to be — the node compiler emits a
16
+ * four-lane broadcast, learns later that one lane of it is read, and cannot go back. Reading the
17
+ * finished stream backwards can: {@link analyze_particle_lanes} already knows the highest live lane
18
+ * of every destination, and this pass writes that width into the instruction.
19
+ *
20
+ * The saving is in slots more often than in instructions. A narrowed value stops occupying the runs
21
+ * above it, which is what lets the register-packing pass reclaim them, and the register file is the
22
+ * interpreter's dominant cost — see the occupancy note in `vm/chunk_particle_vm.js`.
23
+ *
24
+ * Lanes are a run from zero, so the width follows the *highest* live lane rather than the count of
25
+ * them: a live lane 2 holds the instruction at three lanes however dead lanes 0 and 1 are. Clearing
26
+ * out a hole in the middle would mean splitting the instruction, which costs more than the lane.
27
+ *
28
+ * A source's swizzle needs no trimming: an operand reaches as far as its selectors below the width,
29
+ * so narrowing the instruction narrows what every source keeps alive by itself.
30
+ *
31
+ * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
32
+ */
33
+ export function pass_narrow_widths(instructions, context) {
34
+ const decoded = decode_particle_instructions(instructions);
35
+ const { keep, width } = analyze_particle_lanes(decoded, context.register_slots);
36
+
37
+ /** @type {number[][]} */
38
+ const out = instructions.slice();
39
+
40
+ let changed = false;
41
+
42
+ for (let i = 0; i < instructions.length; i++) {
43
+ const instruction = decoded[i];
44
+
45
+ // Instructions nothing keeps are the dead-code pass's to remove, not this one's to narrow.
46
+ if (!keep[i] || width[i] === instruction.width) {
47
+ continue;
48
+ }
49
+
50
+ const words = instruction.words.slice();
51
+
52
+ words[0] = vm_with_width(words[0], width[i]);
53
+
54
+ if (!particle_instruction_is_well_formed(words)) {
55
+ continue;
56
+ }
57
+
58
+ out[i] = words;
59
+ changed = true;
60
+ }
61
+
62
+ return changed ? out : null;
63
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"pass_pack_registers.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_pack_registers.js"],"names":[],"mappings":"AAyEiB,sJAKN;AA5EX,qBAAqB;AACrB,2CADW,MAAM,CAC4C"}
1
+ {"version":3,"file":"pass_pack_registers.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_pack_registers.js"],"names":[],"mappings":"AAuF09C,sJAAqP;AApF/sD,qBAAqB;AACrB,2CADW,MAAM,CAC4C"}
@@ -1,86 +1,87 @@
1
- import { decode_particle_instructions, particle_instruction_is_well_formed } from "./particle_program_analysis.js";
2
-
3
- /** @type {string} */
4
- export const PARTICLE_PASS_PACK_REGISTERS = "pack_registers";
5
-
6
- /**
7
- * Close the holes the other passes left in the register file.
8
- *
9
- * Everything before this frees slots without moving anything into them: dead code takes whole values
10
- * out of the middle of the file, narrowing takes the top lanes off the ones that remain, and both
11
- * leave the survivors exactly where the frontend's allocator put them. The declared register count
12
- * is then the high-water mark of a file that is mostly gaps — and the count is what the interpreter
13
- * actually pays for, since `vm_reg` is a `var<private>` array indexed dynamically and its size sets
14
- * the shader's register footprint outright (see the occupancy note in `vm/chunk_particle_vm.js`).
15
- *
16
- * ## Why it is a compaction and not a re-allocation
17
- *
18
- * Registers are not in SSA form: a slot is written, read, and written again by something unrelated,
19
- * and two values that never overlap in time may already be sharing one. Reassigning slots by live
20
- * range would mean reconstructing what the frontend's allocator knew and discarding what it decided.
21
- *
22
- * Deleting the slots nothing touches at all needs none of that, and is safe by construction. The
23
- * remap is order-preserving and injective over used slots, so every operand run — whose slots are
24
- * all used, by definition of being an operand — stays contiguous and keeps its length; two runs that
25
- * named the same slots still do, and two that were disjoint still are. Nothing about the operand
26
- * overlap rule can be broken by squeezing out slots that appear in no operand at all.
27
- *
28
- * A slot read but never written stays in the file, holding the zero the reset gave it.
29
- *
30
- * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
31
- */
32
- export function pass_pack_registers(instructions, context) {
33
- const decoded = decode_particle_instructions(instructions);
34
- const slots = context.register_slots;
35
- const used = new Uint8Array(slots);
36
-
37
- for (const instruction of decoded) {
38
- const runs = instruction.write === null ? instruction.reads : [instruction.write, ...instruction.reads];
39
-
40
- for (const run of runs) {
41
- for (let lane = 0; lane < run.span; lane++) {
42
- if (run.base + lane < slots) {
43
- used[run.base + lane] = 1;
44
- }
45
- }
46
- }
47
- }
48
-
49
- const remap = new Int32Array(slots).fill(-1);
50
-
51
- let next = 0;
52
- let moved = false;
53
-
54
- for (let slot = 0; slot < slots; slot++) {
55
- if (used[slot]) {
56
- moved = moved || next !== slot;
57
- remap[slot] = next++;
58
- }
59
- }
60
-
61
- if (!moved) {
62
- return null;
63
- }
64
-
65
- /** @type {number[][]} */
66
- const out = [];
67
-
68
- for (const instruction of decoded) {
69
- const words = instruction.words.slice();
70
- const runs = instruction.write === null ? instruction.reads : [instruction.write, ...instruction.reads];
71
-
72
- for (const run of runs) {
73
- // The destination slot carries a register for value-producing opcodes and a source for
74
- // `STORE_ATTR` and `KILL`; either way it is word 1, and a source operand is word 2 + n.
75
- words[run.operand < 0 ? 1 : 2 + run.operand] = remap[run.base];
76
- }
77
-
78
- if (!particle_instruction_is_well_formed(words)) {
79
- return null;
80
- }
81
-
82
- out.push(words);
83
- }
84
-
85
- return out;
86
- }
1
+ import { vm_operand_with_base, vm_with_dst } from "../isa/ParticleVMISA.js";
2
+ import { decode_particle_instructions, particle_instruction_is_well_formed } from "./particle_program_analysis.js";
3
+
4
+ /** @type {string} */
5
+ export const PARTICLE_PASS_PACK_REGISTERS = "pack_registers";
6
+
7
+ /**
8
+ * Close the holes the other passes left in the register file.
9
+ *
10
+ * Everything before this frees slots without moving anything into them: dead code takes whole values
11
+ * out of the middle of the file, narrowing takes the top lanes off the ones that remain, and both
12
+ * leave the survivors exactly where the frontend's allocator put them. The declared register count
13
+ * is then the high-water mark of a file that is mostly gaps — and the count is what the interpreter
14
+ * actually pays for, since `vm_reg` is a `var<private>` array indexed dynamically and its size sets
15
+ * the shader's register footprint outright (see the occupancy note in `vm/chunk_particle_vm.js`).
16
+ *
17
+ * ## Why it is a compaction and not a re-allocation
18
+ *
19
+ * Registers are not in SSA form: a slot is written, read, and written again by something unrelated,
20
+ * and two values that never overlap in time may already be sharing one. Reassigning slots by live
21
+ * range would mean reconstructing what the frontend's allocator knew and discarding what it decided.
22
+ *
23
+ * Deleting the slots nothing touches at all needs none of that, and is safe by construction. Every
24
+ * slot of every operand's span is marked used — including the ones inside a span that a swizzle
25
+ * skips over — so the remap is order-preserving and injective over the slots any operand can name,
26
+ * and every run stays contiguous with its swizzle meaning what it did.
27
+ *
28
+ * A slot read but never written stays in the file, holding the zero the reset gave it.
29
+ *
30
+ * @type {import("./optimize_particle_program.js").ParticleOptimizerPass}
31
+ */
32
+ export function pass_pack_registers(instructions, context) {
33
+ const decoded = decode_particle_instructions(instructions);
34
+ const slots = context.register_slots;
35
+ const used = new Uint8Array(slots);
36
+
37
+ for (const instruction of decoded) {
38
+ const runs = instruction.write === null ? instruction.reads : [instruction.write, ...instruction.reads];
39
+
40
+ for (const run of runs) {
41
+ for (let lane = 0; lane < run.span; lane++) {
42
+ if (run.base + lane < slots) {
43
+ used[run.base + lane] = 1;
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ const remap = new Int32Array(slots).fill(-1);
50
+
51
+ let next = 0;
52
+ let moved = false;
53
+
54
+ for (let slot = 0; slot < slots; slot++) {
55
+ if (used[slot]) {
56
+ moved = moved || next !== slot;
57
+ remap[slot] = next++;
58
+ }
59
+ }
60
+
61
+ if (!moved) {
62
+ return null;
63
+ }
64
+
65
+ /** @type {number[][]} */
66
+ const out = [];
67
+
68
+ for (const instruction of decoded) {
69
+ const words = instruction.words.slice();
70
+
71
+ if (instruction.write !== null) {
72
+ words[0] = vm_with_dst(words[0], remap[instruction.write.base]);
73
+ }
74
+
75
+ for (const read of instruction.reads) {
76
+ words[1 + read.operand] = vm_operand_with_base(read.word, remap[read.base]);
77
+ }
78
+
79
+ if (!particle_instruction_is_well_formed(words)) {
80
+ return null;
81
+ }
82
+
83
+ out.push(words);
84
+ }
85
+
86
+ return out;
87
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"pass_peephole.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_peephole.js"],"names":[],"mappings":"AAsF6C,gJAO1B;AApFnB,qBAAqB;AACrB,qCADW,MAAM,CACgC"}
1
+ {"version":3,"file":"pass_peephole.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/optimizer/pass_peephole.js"],"names":[],"mappings":"AA+GC,gJAMW;AA1GZ,qBAAqB;AACrB,qCADW,MAAM,CACgC"}