@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
@@ -9,16 +9,20 @@ import {
9
9
  PARTICLE_SIMULATE_WORKGROUP_SIZE,
10
10
  PARTICLE_SORT_BUCKET_COUNT,
11
11
  PARTICLE_SPAWN_COMMAND_WORDS,
12
+ PARTICLE_VM_FAST_REGISTER_SLOTS,
12
13
  } from "./ParticleConstants.js";
13
14
  import { PARTICLE_COUNTER, PARTICLE_COUNTER_COUNT } from "./data/PARTICLE_COUNTERS.js";
14
- import { graph_particles_render, graph_particles_simulate } from "./graph_particles.js";
15
+ import { graph_particles_simulate } from "./graph_particles.js";
15
16
  import {
16
17
  graph_particle_avboit_draw,
17
18
  graph_particle_avboit_occupancy,
18
19
  graph_particle_avboit_splat,
19
20
  } from "./graph_particles_avboit.js";
21
+ import { graph_particles_billboard } from "./graph_particles_billboard.js";
22
+ import { ParticleRenderMode } from "./ParticleRenderMode.js";
20
23
  import { EmitterRegistry } from "./runtime/EmitterRegistry.js";
21
24
  import { create_particle_billboard_pipeline } from "./shaders/shader_particle_render.js";
25
+ import { graph_particle_sort } from "./sort/graph_particle_sort.js";
22
26
 
23
27
  const WORD = Uint32Array.BYTES_PER_ELEMENT;
24
28
 
@@ -33,16 +37,29 @@ const INDIRECT = GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT | GPUBufferUsa
33
37
  * ## What it owns
34
38
  *
35
39
  * Every piece of persistent GPU state: the particle pool, the ping-pong alive lists, the dead
36
- * free-list, the counters, both indirect-args buffers, the simulation-order (coherence) and
37
- * render-order (sort) scratch, the emitter database (the emitter table and the GPU-owned state
38
- * table, one buffer), the packed program buffer, and the spawn-command ring. Buffers that depend
39
- * on the emitter set — the coherence scratch on the number of distinct programs, the program
40
- * buffer on the arena, the database on its own pages — are grown inside {@link execute}, the way
41
- * ReSTIR's reservoirs follow the resolution.
40
+ * free-list, the counters, both indirect-args buffers, the simulation-order (coherence) scratch,
41
+ * the emitter database (the emitter table and the GPU-owned state table, one buffer), the packed
42
+ * program buffer, and the spawn-command ring. Buffers that depend on the emitter set — the
43
+ * coherence scratch on the number of distinct programs, the program buffer on the heap, the
44
+ * database on its own pages — are grown inside {@link execute}, the way ReSTIR's reservoirs follow
45
+ * the resolution. The render-order (sort) scratch is not in that list because it is not
46
+ * unconditional: see below.
42
47
  *
43
48
  * Every pass stays within the eight storage buffers a stage gets by default: the emitter record
44
49
  * and the GPU-owned state are two tables of one database buffer, and the VM's constants and code
45
- * are one packed buffer.
50
+ * are one packed buffer. The one exception is the wide-register fallback (below), whose emit and
51
+ * simulate passes bind a ninth for the register file — inside the ten the engine already demands of
52
+ * an adapter, but past the default.
53
+ *
54
+ * ## Two interpreters
55
+ *
56
+ * The VM's register file normally lives in shader registers, and is therefore small — see
57
+ * {@link ./ParticleConstants.js PARTICLE_VM_FAST_REGISTER_SLOTS}. An effect whose compiled program
58
+ * needs more than it holds does not fail: the whole system swaps emit and simulate for variants
59
+ * that keep the file in a storage buffer, which is far slower and effectively unbounded. The choice
60
+ * is per-frame, whole-system, and made here — the registry reports `max_register_count` over the
61
+ * effects it holds and this is where that number meets the VM's; nothing about authoring a graph has
62
+ * a register ceiling.
46
63
  *
47
64
  * ## Emitters are scene nodes
48
65
  *
@@ -61,15 +78,20 @@ const INDIRECT = GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT | GPUBufferUsa
61
78
  * command list that a pass adds to the emitter's pending spawns, on the same path as everything
62
79
  * else. See `graph_particles.js` for the frame.
63
80
  *
64
- * ## Drawing
81
+ * ## Drawing, and the one thing the mode changes
82
+ *
83
+ * {@link execute} is the whole per-frame call, once per frame. It always records everything that
84
+ * moves particles and leaves the alive list and the indirect draw args as graph handles; what it
85
+ * records after that is the {@link ParticleRenderMode} it was given.
65
86
  *
66
- * {@link simulate} records everything that moves particles and leaves the alive list and the
67
- * indirect draw args as graph handles. Two things draw them. Under the renderer the system is an
68
- * `AVBOITSideChannel`: the transparency orchestrator asks it for its occupancy, its extinction and
69
- * its draw at the three points where the transparent meshes have contributed theirs
70
- * ({@link avboit_occupancy}, {@link avboit_splat}, {@link avboit_draw}), and the particles
71
- * composite order-independently with them. A page without that pipeline calls {@link execute},
72
- * which sorts and draws the billboards straight over a colour target.
87
+ * `BILLBOARD` sorts the alive list back-to-front and draws it over a colour target, because
88
+ * premultiplied over-blending is order-dependent. `AVBOIT` records neither: under the renderer the
89
+ * system is an `AVBOITSideChannel`, and the transparency orchestrator asks it for its occupancy, its
90
+ * extinction and its draw at the three points where the transparent meshes have contributed theirs
91
+ * ({@link avboit_occupancy}, {@link avboit_splat}, {@link avboit_draw}). Those read the same handles
92
+ * and composite into a volume and a set of accumulators that are sums, so an ordering would buy
93
+ * nothing — and the sort is four passes and a scan over every live particle, plus two lists a word
94
+ * per particle each, which is why the mode also decides whether those buffers exist at all.
73
95
  *
74
96
  * ## Allocation
75
97
  *
@@ -123,7 +145,7 @@ export class GPUParticleSystem {
123
145
 
124
146
  /**
125
147
  * View-depth range the render sort quantises: particles nearer than `[0]` share the front bin,
126
- * farther than `[1]` the back one.
148
+ * farther than `[1]` the back one. Read only by {@link ParticleRenderMode.BILLBOARD}.
127
149
  * @type {Float32Array}
128
150
  */
129
151
  sort_depth_range = new Float32Array([0.1, 100]);
@@ -139,7 +161,7 @@ export class GPUParticleSystem {
139
161
  atlas_sampler;
140
162
 
141
163
  /**
142
- * The persistent GPU buffers, by the names {@link graph_particles} binds them under. Exposed for
164
+ * The persistent GPU buffers, by the names the graph functions bind them under. Exposed for
143
165
  * inspection — a harness copying the counters out to display them — never for the frame loop,
144
166
  * which reads nothing back. Entries that grow with the emitter set are replaced in place.
145
167
  *
@@ -207,11 +229,11 @@ export class GPUParticleSystem {
207
229
  #pipeline_key = "";
208
230
 
209
231
  /**
210
- * Per-frame scalars handed to {@link graph_particles}, reused rather than rebuilt.
232
+ * Per-frame scalars handed to {@link graph_particles_simulate}, reused rather than rebuilt.
211
233
  * @type {object}
212
234
  */
213
235
  #frame = {
214
- dt: 0, time: 0, index: 0, max_catchup: 1, spawn_command_count: 0, sort_near: 0.1, sort_far: 100,
236
+ dt: 0, time: 0, index: 0, max_catchup: 1, spawn_command_count: 0,
215
237
  };
216
238
 
217
239
  /** @type {{capacity: number, group_count: number}} */
@@ -275,16 +297,20 @@ export class GPUParticleSystem {
275
297
  }
276
298
 
277
299
  /**
278
- * Number of simulation-order buckets — one per distinct compiled program.
300
+ * Number of simulation-order buckets — one per program id the registry can hand out, which is
301
+ * its peak number of distinct compiled programs rather than its current one.
279
302
  *
280
303
  * This is the coherence pass's only host-provided number, and it is static topology rather than
281
- * per-frame state: it changes when a new effect is registered, not as particles are born and
282
- * die. Everything the pass measures per frame stays on the GPU.
304
+ * per-frame state: it changes when an effect the set has never held is registered, not as
305
+ * particles are born and die. Everything the pass measures per frame stays on the GPU. Sizing it
306
+ * from the peak rather than the live count is what keeps it from moving every time an effect is
307
+ * unregistered — the bins of released ids are empty, and an empty bin rounds up to zero
308
+ * workgroups and shifts nothing after it.
283
309
  *
284
310
  * @returns {number}
285
311
  */
286
312
  bucketCount() {
287
- return Math.max(1, this.registry.program_count);
313
+ return Math.max(1, this.registry.program_id_capacity);
288
314
  }
289
315
 
290
316
  /**
@@ -305,20 +331,23 @@ export class GPUParticleSystem {
305
331
  */
306
332
  spawn(emitter, count) {
307
333
  assert.defined(emitter, "emitter");
308
- assert.notEqual(emitter.row, -1, "emitter is not in the scene");
309
334
  assert.isNonNegativeInteger(count, "count");
310
335
 
336
+ const context = this.registry.context(emitter);
337
+
338
+ assert.defined(context, "emitter is not in the scene");
339
+
311
340
  const ring = this.#spawn_commands;
312
341
  const base = this.#spawn_command_count * PARTICLE_SPAWN_COMMAND_WORDS;
313
342
 
314
343
  if (base >= ring.length) {
315
- // the text is the key warn_limited counts on, so it carries no burst size: one message
316
- // per ring size, not one per number a caller happens to ask for
344
+ // the text is the key warn_limited counts on, so it carries no burst size: one message
345
+ // per ring size, not one per number a caller happens to ask for
317
346
  warn_limited(`GPUParticleSystem: spawn command ring is full (${ring.length / PARTICLE_SPAWN_COMMAND_WORDS} per frame); dropping this frame's remaining bursts`);
318
347
  return;
319
348
  }
320
349
 
321
- ring[base] = emitter.row;
350
+ ring[base] = context.row;
322
351
  ring[base + 1] = count;
323
352
  this.#spawn_command_emitters[this.#spawn_command_count] = emitter;
324
353
  this.#spawn_command_count++;
@@ -327,32 +356,16 @@ export class GPUParticleSystem {
327
356
  /**
328
357
  * The simulation half of the frame: reconcile the emitter set with the scene, push what changed
329
358
  * to the GPU, and record every pass that moves particles — through to the indirect draw args.
330
- * What it leaves as graph handles is what a draw consumes: {@link execute} draws them
331
- * standalone, and the AVBOIT side-channel methods below draw them through the renderer's
332
- * transparency pipeline.
359
+ * What it leaves as graph handles is what a draw consumes, whichever draw that turns out to be.
333
360
  *
334
- * Call after the scene context has built for the frame (`GPUSceneContext#update`), so every
335
- * emitter node has its `transforms` row, and after the hierarchy pass has run, so the rows'
336
- * `global` matrices are this frame's.
337
- *
338
- * **Once per frame, not once per view.** This advances the simulation by `dt` and hands out
339
- * handles into the graph it recorded into; a second view of the same scene records a second
340
- * graph and would step the simulation twice. The renderer has one view per `render` call today,
341
- * so this holds by construction; a second view of one scene needs the step and the handles
342
- * separated — record the passes for the first graph, import the same buffers into the rest.
343
- *
344
- * @param {object} params
361
+ * @param {object} params see {@link execute}
345
362
  * @param {import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} params.graph
346
- * @param {number} params.camera graph handle of the camera uniform buffer
347
- * @param {number} params.scene_database graph handle of the scene database — the one the
348
- * hierarchy pass returned, so this reads the matrices it composed
349
- * @param {number} params.dt seconds since the previous frame
363
+ * @param {number} params.camera
364
+ * @param {number} params.scene_database
365
+ * @param {number} params.dt
350
366
  * @returns {import("./graph_particles.js").ParticleSimulationHandles}
351
367
  */
352
- simulate({ graph, camera, scene_database, dt }) {
353
- assert.defined(graph, "graph");
354
- assert.isNumber(dt, "dt");
355
-
368
+ #simulate({ graph, camera, scene_database, dt }) {
356
369
  this.#sync_membership();
357
370
  this.#upload();
358
371
 
@@ -362,8 +375,6 @@ export class GPUParticleSystem {
362
375
  frame.index = this.frame;
363
376
  frame.max_catchup = this.max_catchup_seconds;
364
377
  frame.spawn_command_count = this.#spawn_command_count;
365
- frame.sort_near = this.sort_depth_range[0];
366
- frame.sort_far = this.sort_depth_range[1];
367
378
 
368
379
  const table = this.registry.table;
369
380
  const emitters = this.#emitters;
@@ -384,6 +395,11 @@ export class GPUParticleSystem {
384
395
  emitters,
385
396
  capacity: this.capacity,
386
397
  bucket_count: this.bucketCount(),
398
+ // Whose register file the VM runs on is decided here, once, for the whole system: the
399
+ // registry reports what the hungriest registered effect needs and this compares it
400
+ // against what the fast file holds. Re-read every frame because registering an emitter —
401
+ // or unregistering the one hungry effect — can flip it either way.
402
+ wide_registers: this.registry.max_register_count > PARTICLE_VM_FAST_REGISTER_SLOTS,
387
403
  frame,
388
404
  });
389
405
 
@@ -404,35 +420,98 @@ export class GPUParticleSystem {
404
420
  }
405
421
 
406
422
  /**
407
- * The whole standalone frame: {@link simulate}, then the depth sort and one billboard draw over
408
- * a colour target with fixed-function blending. For a page without the renderer's transparency
409
- * pipeline; under the renderer the drawing is AVBOIT's.
423
+ * The system's whole contribution to the frame: the simulation, then whatever `mode` says draws
424
+ * it.
425
+ *
426
+ * {@link ParticleRenderMode.BILLBOARD} adds the depth sort and one billboard draw over `color`
427
+ * with fixed-function blending, for a page with no transparency pipeline of its own.
428
+ * {@link ParticleRenderMode.AVBOIT} adds nothing: the orchestrator draws the particles later in
429
+ * the frame through {@link avboit_occupancy}, {@link avboit_splat} and {@link avboit_draw}, off
430
+ * the handles this just produced, and its accumulators are order-independent — so the sort is
431
+ * skipped and its buffers are never allocated. `color` comes straight back either way, so a
432
+ * caller can assign the result unconditionally and let the mode be the only difference.
410
433
  *
411
- * @param {object} params every parameter of {@link simulate}, plus a target to draw over
434
+ * Call after the scene context has built for the frame (`GPUSceneContext#update`), so every
435
+ * emitter node has its `transforms` row, and after the hierarchy pass has run, so the rows'
436
+ * `global` matrices are this frame's.
437
+ *
438
+ * **Once per frame, not once per view.** This advances the simulation by `dt` and hands out
439
+ * handles into the graph it recorded into; a second view of the same scene records a second
440
+ * graph and would step the simulation twice. The renderer has one view per `render` call today,
441
+ * so this holds by construction; a second view of one scene needs the step and the handles
442
+ * separated — record the passes for the first graph, import the same buffers into the rest.
443
+ *
444
+ * @param {object} params
412
445
  * @param {import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} params.graph
413
446
  * @param {number} params.camera graph handle of the camera uniform buffer
414
- * @param {number} params.scene_database graph handle of the scene database
447
+ * @param {number} params.scene_database graph handle of the scene database — the one the
448
+ * hierarchy pass returned, so this reads the matrices it composed
415
449
  * @param {number} params.dt seconds since the previous frame
416
- * @param {number} params.color graph handle of the colour target to draw over
417
- * @param {number} params.depth graph handle of the scene depth (tested, never written)
418
- * @returns {number} the colour handle after the particle draw
419
- */
420
- execute({ graph, camera, scene_database, color, depth, dt }) {
421
- const simulated = this.simulate({ graph, camera, scene_database, dt });
450
+ * @param {ParticleRenderMode} [params.mode] who draws, and so whether there is a sort
451
+ * @param {number} [params.color] graph handle of the colour target to draw over. Required by
452
+ * `BILLBOARD`; returned untouched by `AVBOIT`
453
+ * @param {number} [params.depth] graph handle of the scene depth (tested, never written).
454
+ * Required by `BILLBOARD`
455
+ * @returns {number|undefined} the colour handle after the particle draw, or `color` unchanged
456
+ */
457
+ execute({ graph, camera, scene_database, color, depth, dt, mode = ParticleRenderMode.BILLBOARD }) {
458
+ assert.defined(graph, "graph");
459
+ assert.isNumber(dt, "dt");
460
+ assert.enum(mode, ParticleRenderMode, "mode");
461
+
462
+ const billboard = mode === ParticleRenderMode.BILLBOARD;
463
+
464
+ // Checked before the simulation rather than at the draw: the simulation advances `frame` and
465
+ // `time` and writes the pool, and a throw after that leaves a frame half-stepped.
466
+ if (billboard) {
467
+ assert.isNonNegativeInteger(color, "color");
468
+ assert.isNonNegativeInteger(depth, "depth");
469
+ }
470
+
471
+ const simulated = this.#simulate({ graph, camera, scene_database, dt });
472
+
473
+ if (!billboard) {
474
+ // AVBOIT: the side channels draw these handles later in the frame, and the colour target
475
+ // is not this call's to touch.
476
+ return color;
477
+ }
478
+
479
+ // Allocated here rather than in the constructor: they are two words per particle plus the
480
+ // bins, and only this mode ever reads them. A system the renderer drives never makes them.
481
+ this.#ensure_sort_buffers();
482
+
483
+ // The render order: back-to-front by view depth, so premultiplied transparency composites
484
+ // correctly. Its two per-particle passes take the dispatch the coherence reset wrote from
485
+ // the GPU's own alive count.
486
+ const sorted = graph_particle_sort({
487
+ graph,
488
+ gpu: this.buffers,
489
+ camera,
490
+ emitter_database: simulated.emitter_database,
491
+ pool: simulated.pool,
492
+ alive: simulated.alive,
493
+ counters: simulated.counters,
494
+ dispatch_args: simulated.sim_dispatch_args,
495
+ bucket_count: PARTICLE_SORT_BUCKET_COUNT,
496
+ near: this.sort_depth_range[0],
497
+ far: this.sort_depth_range[1],
498
+ });
422
499
 
423
500
  const render = this.#render;
424
501
  render.atlas = this.atlas;
425
502
  render.atlas_sampler = this.atlas_sampler;
426
503
 
427
- return graph_particles_render({
504
+ // One instanced billboard draw over the sorted list, sized by the draw args this frame's
505
+ // build-indirect wrote.
506
+ return graph_particles_billboard({
428
507
  graph,
429
508
  camera,
430
509
  color,
431
510
  depth,
432
- gpu: this.buffers,
433
- simulated,
434
- sort_bucket_count: PARTICLE_SORT_BUCKET_COUNT,
435
- frame: this.#frame,
511
+ pool: simulated.pool,
512
+ draw_list: sorted,
513
+ emitter_database: simulated.emitter_database,
514
+ draw_args: simulated.draw_args,
436
515
  render,
437
516
  });
438
517
  }
@@ -447,7 +526,7 @@ export class GPUParticleSystem {
447
526
  #simulated_for(graph) {
448
527
  const current = this.#simulated;
449
528
 
450
- assert.equal(current.graph, graph, "the particles were not simulated into this graph this frame — call simulate() before the transparency pipeline records");
529
+ assert.equal(current.graph, graph, "the particles were not simulated into this graph this frame — call execute() before the transparency pipeline records");
451
530
 
452
531
  return current;
453
532
  }
@@ -580,7 +659,7 @@ export class GPUParticleSystem {
580
659
  continue;
581
660
  }
582
661
 
583
- if (node.row === -1) {
662
+ if (registry.context(node) === undefined) {
584
663
  registry.add(node, transform_row);
585
664
  } else {
586
665
  registry.set_transform_row(node, transform_row);
@@ -672,8 +751,9 @@ export class GPUParticleSystem {
672
751
  for (let i = 0; i < count; i++) {
673
752
  const emitter = emitters[i];
674
753
  const row = ring[i * PARTICLE_SPAWN_COMMAND_WORDS];
754
+ const context = this.registry.context(emitter);
675
755
 
676
- if (emitter.row === row) {
756
+ if (context !== undefined && context.row === row) {
677
757
  rows[row] += ring[i * PARTICLE_SPAWN_COMMAND_WORDS + 1];
678
758
  }
679
759
 
@@ -732,6 +812,30 @@ export class GPUParticleSystem {
732
812
  this.#sim_bucket_capacity = buckets;
733
813
  }
734
814
 
815
+ /**
816
+ * The render-order scratch, made on the first frame that actually sorts.
817
+ *
818
+ * Only {@link ParticleRenderMode.BILLBOARD} reads any of it, and the two per-particle lists are
819
+ * a word per particle each — at the renderer's default capacity, half a megabyte that AVBOIT
820
+ * would never touch. Nothing in them outlives a frame, so there is nothing to carry over and the
821
+ * first sorted frame is as correct as any later one.
822
+ */
823
+ #ensure_sort_buffers() {
824
+ const buffers = this.buffers;
825
+
826
+ if (buffers.sorted !== undefined) {
827
+ return;
828
+ }
829
+
830
+ const device = this.graphics.device;
831
+ const capacity = this.capacity;
832
+
833
+ buffers.sorted = device.createBuffer({ label: "particles/sorted", size: capacity * WORD, usage: STORAGE });
834
+ buffers.sort_keys = device.createBuffer({ label: "particles/sort_keys", size: capacity * WORD, usage: STORAGE });
835
+ buffers.sort_histogram = device.createBuffer({ label: "particles/sort_histogram", size: (PREFIX_SCAN_CSDLDF_HEADER_WORDS + align_4(PARTICLE_SORT_BUCKET_COUNT)) * WORD, usage: STORAGE });
836
+ buffers.sort_cursor = device.createBuffer({ label: "particles/sort_cursor", size: PARTICLE_SORT_BUCKET_COUNT * WORD, usage: STORAGE });
837
+ }
838
+
735
839
  /**
736
840
  * The buffers whose size is fixed by the pool capacity, and the free list's initial contents.
737
841
  */
@@ -754,12 +858,6 @@ export class GPUParticleSystem {
754
858
  buffers.draw_args = device.createBuffer({ label: "particles/draw_args", size: 4 * WORD, usage: INDIRECT });
755
859
  buffers.sim_dispatch_args = device.createBuffer({ label: "particles/sim_dispatch_args", size: 3 * WORD, usage: INDIRECT });
756
860
 
757
- // Render order.
758
- buffers.sorted = device.createBuffer({ label: "particles/sorted", size: capacity * WORD, usage: STORAGE });
759
- buffers.sort_keys = device.createBuffer({ label: "particles/sort_keys", size: capacity * WORD, usage: STORAGE });
760
- buffers.sort_histogram = device.createBuffer({ label: "particles/sort_histogram", size: (PREFIX_SCAN_CSDLDF_HEADER_WORDS + align_4(PARTICLE_SORT_BUCKET_COUNT)) * WORD, usage: STORAGE });
761
- buffers.sort_cursor = device.createBuffer({ label: "particles/sort_cursor", size: PARTICLE_SORT_BUCKET_COUNT * WORD, usage: STORAGE });
762
-
763
861
  buffers.spawn_commands = device.createBuffer({ label: "particles/spawn_commands", size: this.#spawn_commands.byteLength, usage: STORAGE });
764
862
 
765
863
  // Every slot free, and the counters saying so.
@@ -874,7 +972,7 @@ export class GPUParticleSystem {
874
972
  /**
875
973
  * A storage buffer holding `data`, replacing `previous` (destroyed) if it exists. The program
876
974
  * buffer is monolithic — a program is variable-length, so there is no table to page it into — and
877
- * is rebuilt whole on the rare frame the arena grows.
975
+ * is rebuilt whole on the rare frame the program heap changes.
878
976
  *
879
977
  * @param {GPUDevice} device
880
978
  * @param {GPUBuffer|undefined} previous
@@ -65,24 +65,33 @@ export const PARTICLE_SORT_BUCKET_COUNT: number;
65
65
  */
66
66
  export const PARTICLE_RECORD_USER_WORD_START: number;
67
67
  /**
68
- * Size of the VM register file, in `f32` slots. A register IS a slot: a `vec3` value is three
68
+ * Register slots the INSTRUCTION SET can name. A register IS a slot: a `vec3` value is three
69
69
  * consecutive ones, and an instruction's width says how many its operands span.
70
70
  *
71
- * This is the interpreter's single largest cost and it is paid by every program, not just the ones
72
- * that need it: `vm_reg` is a `var<private>` array the VM indexes dynamically, which lands in
73
- * registers rather than scratch, so the file's size sets the shader's register footprint outright.
74
- * Compiled to RDNA2 (gfx1030, wave32), 32 slots cost 47 VGPRs against a 16-wave occupancy cap that
75
- * anything at or below 64 VGPRs reaches. Sixteen `vec4` registers — what this was — cost 81 and
76
- * held the shader to 10 waves.
71
+ * This is an encoding fact, not a shader's budget. A destination is the 8-bit `VM_DST_MASK` field
72
+ * of word 0 and every source base is the 8-bit `VM_OPERAND_BASE_MASK` field of its own word, so 256
73
+ * is exactly what an instruction can address and reaching the ceiling costs nothing. Past it the
74
+ * instruction word would have to grow — there is room (word 0 has bits 11..15 and 22..23 free, and
75
+ * each operand word uses only its low 16) — but nothing needs it yet.
77
76
  *
78
- * Scalar slots are also what makes the number go further than the same count of floats did as
79
- * `vec4`s: eight `vec4` registers hold eight values whatever their width, while 32 slots hold ten
80
- * `vec3`s or 32 scalars. The playground's fire effect, the most involved in the tree, peaks at 11
81
- * slots live.
77
+ * What a *shader* can afford is a different and much smaller number, see
78
+ * {@link PARTICLE_VM_FAST_REGISTER_SLOTS}. The graph compiler allocates against this one, records
79
+ * the peak as the program's `register_count`, and the runtime picks an interpreter from it.
82
80
  *
83
- * A graph that needs more gets a clear error out of `compile_particle_graph.js` rather than silent
84
- * corruption, and the fix for it is to raise this number and re-measure — not to assume the headroom
85
- * was free.
81
+ * @type {number}
82
+ */
83
+ export const PARTICLE_VM_REGISTER_SLOTS: number;
84
+ /**
85
+ * Register slots the FAST interpreter's file holds — `vm_reg` in
86
+ * {@link ./vm/chunk_particle_vm_registers_fast.js}, a `var<private>` array the VM indexes
87
+ * dynamically. It lands in registers rather than scratch, so this number is the shader's register
88
+ * footprint outright, and every program pays it rather than only the ones that need it.
89
+ *
90
+ * Compiled to RDNA2 (gfx1030, wave32), 32 slots cost 47 VGPRs; sixteen `vec4` registers — what this
91
+ * was — cost 81 and held the shader to 10 waves against a 16-wave cap that anything at or below 64
92
+ * VGPRs reaches. Scalar slots are also what makes the number go further than the same count of
93
+ * floats did as `vec4`s: eight `vec4` registers hold eight values whatever their width, while 32
94
+ * slots hold ten `vec3`s or 32 scalars.
86
95
  *
87
96
  * ## Why 48 and not 32
88
97
  *
@@ -91,21 +100,48 @@ export const PARTICLE_RECORD_USER_WORD_START: number;
91
100
  * any of them: measured peaks are 26 for `simplex3`, 33 for `simplex4`, 32 for `curl3` and 40 for
92
101
  * `curl4` — the last with a whole effect's worth of arithmetic still to fit around it.
93
102
  *
94
- * 48 is the largest number that the measurement above says is free. At 32 slots the shader compiled
95
- * to 47 VGPRs, and a slot is about a VGPR, so 48 lands around 63 — still at or under the 64 that
96
- * reaches the 16-wave occupancy cap. **That arithmetic has not been re-measured against a real
97
- * driver.** It is the model the paragraphs above were written from, and it is a model; anyone
98
- * changing this number again, or wanting to be sure of this one, should compile the simulate shader
99
- * offline and read the register count rather than trust it.
103
+ * 48 was picked by extrapolating the 32-slot measurement: a slot is about a VGPR, so 48 should land
104
+ * near 63, at or under the 64 that reaches the occupancy cap. **That extrapolation was wrong.** The
105
+ * measured table in {@link ./vm/chunk_particle_vm.js} puts this interpreter at 80 VGPRs on a 48-slot
106
+ * file, well past the cap it was sized to stay under. The number stays because it is measured and
107
+ * shipped, not because the model that chose it holds; anyone moving it should compile the simulate
108
+ * shader offline and read the register count rather than extrapolate again.
109
+ *
110
+ * ## What happens above it
111
+ *
112
+ * Nothing fails. A program whose `register_count` exceeds this is one the fast file cannot hold, and
113
+ * the system falls back to the wide interpreter for the frame — every program, not only the one that
114
+ * overflowed. That is the library declining to have an authoring ceiling, at the price of an
115
+ * interpreter that keeps its registers in storage. See {@link PARTICLE_VM_WIDE_LAUNCH_LANES} and
116
+ * {@link ./vm/chunk_particle_vm_registers_wide.js}.
100
117
  *
101
118
  * @type {number}
102
119
  */
103
- export const PARTICLE_VM_REGISTER_SLOTS: number;
120
+ export const PARTICLE_VM_FAST_REGISTER_SLOTS: number;
104
121
  /**
105
- * Number of `u32` words per VM instruction: `[op, dst, s0, s1, s2]`.
122
+ * Invocations the wide-register simulate and emit passes launch, whatever the particle count.
123
+ *
124
+ * The wide interpreter keeps its register file in a storage buffer, so it needs one file per
125
+ * *invocation in flight*. One lane per particle would size that buffer by pool capacity — a million
126
+ * particles would want a gigabyte — so the wide passes do not run one lane per particle. They launch
127
+ * this many lanes and walk their input with a grid-stride loop, which caps the file count at a
128
+ * constant chosen here instead of at whatever the pool holds.
129
+ *
130
+ * The buffer is `PARTICLE_VM_WIDE_LAUNCH_LANES * PARTICLE_VM_REGISTER_SLOTS * 4` bytes — 8 MiB at
131
+ * these values. It is transient: never cleared, never read back, and shared by the emit and simulate
132
+ * passes, which cannot overlap. See {@link ./vm/chunk_particle_vm_registers_wide.js} for why not
133
+ * clearing it is safe.
134
+ *
135
+ * Must be a multiple of {@link PARTICLE_SIMULATE_WORKGROUP_SIZE}, and of
136
+ * {@link PARTICLE_EMIT_WORKGROUP_SIZE}. The grid stride IS this number, so every iteration has to
137
+ * cover a workgroup-aligned span of the coherence pass's list; a misaligned stride would put two
138
+ * programs in one wave and the wave-uniform section decode would then run one program's code over
139
+ * the other's particles.
140
+ *
106
141
  * @type {number}
107
142
  */
108
- export const PARTICLE_VM_INSTRUCTION_WORDS: number;
143
+ export const PARTICLE_VM_WIDE_LAUNCH_LANES: number;
144
+ export { PARTICLE_VM_INSTRUCTION_WORDS } from "./isa/ParticleVMISA.js";
109
145
  /**
110
146
  * Hard cap on instructions executed by a single VM program invocation. A safety bound so a malformed
111
147
  * program can never spin the GPU; the interpreter's loop is `for (i in 0..LIMIT)`.
@@ -1 +1 @@
1
- {"version":3,"file":"ParticleConstants.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/ParticleConstants.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;GASG;AACH,yCAFU,MAAM,CAE6B;AAE7C;;;;GAIG;AACH,6CAFU,MAAM,CAEgC;AAEhD;;;;;;GAMG;AACH,mDAFU,MAAM,CAEuC;AAEvD;;;GAGG;AACH,2CAFU,MAAM,CAE8B;AAE9C;;;;;;;;;GASG;AACH,4CAFU,MAAM,CAE+B;AAE/C;;;GAGG;AACH,8CAFU,MAAM,CAEiC;AAEjD;;;;;;GAMG;AACH,yCAFU,MAAM,CAE+B;AAE/C;;;GAGG;AACH,8CAFU,MAAM,CAEiC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,yCAFU,MAAM,CAE6B;AAE7C;;;GAGG;AACH,4CAFU,MAAM,CAE+B;AAE/C;;;;;;;;;;;;;;;GAeG;AACH,2CAFU,MAAM,CAEiC;AAEjD;;;;;;;;;;;;;;;GAeG;AACH,+CAFU,MAAM,CAEmC;AAEnD;;;;;;;;;;;;GAYG;AACH,oCAFU,MAAM,CAEgC;AAEhD;;;;;;;;;;GAUG;AACH,uCAFU,MAAM,CAE4B"}
1
+ {"version":3,"file":"ParticleConstants.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/ParticleConstants.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;GASG;AACH,yCAFU,MAAM,CAE6B;AAE7C;;;;GAIG;AACH,6CAFU,MAAM,CAEgC;AAEhD;;;;;;GAMG;AACH,mDAFU,MAAM,CAEuC;AAEvD;;;GAGG;AACH,2CAFU,MAAM,CAE8B;AAE9C;;;;;;;;;GASG;AACH,4CAFU,MAAM,CAE+B;AAE/C;;;GAGG;AACH,8CAFU,MAAM,CAEiC;AAEjD;;;;;;GAMG;AACH,yCAFU,MAAM,CAE+B;AAE/C;;;GAGG;AACH,8CAFU,MAAM,CAEiC;AAEjD;;;;;;;;;;;;;;;GAeG;AACH,yCAFU,MAAM,CAE8B;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,8CAFU,MAAM,CAEkC;AAElD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,4CAFU,MAAM,CAEkC;;AASlD;;;;;;;;;;;;;;;GAeG;AACH,2CAFU,MAAM,CAEiC;AAEjD;;;;;;;;;;;;;;;GAeG;AACH,+CAFU,MAAM,CAEmC;AAEnD;;;;;;;;;;;;GAYG;AACH,oCAFU,MAAM,CAEgC;AAEhD;;;;;;;;;;GAUG;AACH,uCAFU,MAAM,CAE4B"}