@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
@@ -4,34 +4,24 @@ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
4
4
  import { COLLECTION_U32_STRUCT_READ } from "../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
5
5
  import { COMPUTE_SHADER_DEFAULT_GROUP_SIZE } from "../../shader/COMPUTE_SHADER_DEFAULT_GROUP_SIZE.js";
6
6
  import { ComputeShader } from "../../shader/ComputeShader.js";
7
- import { chunk_lower_bound_branchless } from "../../shader/chunk/math/chunk_lower_bound_branchless.js";
8
7
  import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
9
8
  import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
10
- import {
11
- PARTICLE_RECORD_HEADER_EMITTER,
12
- PARTICLE_RECORD_USER_WORD_START,
13
- PARTICLE_RECORD_WORD_COUNT,
14
- PARTICLE_VM_INSTRUCTION_WORDS,
15
- } from "../ParticleConstants.js";
16
9
  import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
17
- import { chunk_particle_header } from "../data/particle_header.js";
10
+ import { chunk_particle_vm_registers_fast } from "../vm/chunk_particle_vm_registers_fast.js";
18
11
  import { chunk_particle_curve_disabled } from "./chunk_particle_curve_disabled.js";
19
- import { chunk_particle_emitter_age } from "./chunk_particle_emitter_age.js";
20
- import { chunk_particle_setup_context } from "./chunk_particle_setup_context.js";
12
+ import { chunk_particle_emit_step } from "./chunk_particle_emit_step.js";
21
13
 
22
14
  /**
23
15
  * The particle emit pass: one thread per particle born this frame.
24
16
  *
25
- * Its input is the prefix scan of the emitter tick pass's per-row spawn counts. Thread `i` finds
26
- * the emitter it belongs to by binary search over the inclusive sums — the first row whose sum
27
- * exceeds `i` — and its place within that emitter's batch from the sum before. That is the
28
- * meshes-to-meshlets expansion applied to particles: the per-emitter count is unbounded, no thread
29
- * loops, and the dispatch is sized on the GPU from the scan's total.
17
+ * Its input is the prefix scan of the emitter tick pass's per-row spawn counts; thread `i` finds the
18
+ * emitter it belongs to by binary search over the inclusive sums, and its place within that
19
+ * emitter's batch from the sum before. Then: pop a free slot from the dead list, clear the record,
20
+ * stamp the header, run the emitter's INIT program, and append the slot to the new alive list.
30
21
  *
31
- * Then, as ever: pop a free slot from the dead list, clear the record, stamp the header with the
32
- * emitter row and its generation, run the emitter's INIT program to give the particle its state,
33
- * and append the slot to the new alive list. The emitter's position and axes come from its scene
34
- * node, so a particle born of an emitter riding a bone starts where the bone is this frame.
22
+ * The per-newborn work is {@link ./chunk_particle_emit_step.js}, shared with
23
+ * {@link ./shader_particle_emit_wide.js}. What this file is, is the *fast* register backing plus the
24
+ * one-lane-per-newborn dispatch that suits it.
35
25
  *
36
26
  * Runs before simulate in the frame so newborns join the same alive list survivors are compacted
37
27
  * into. Shares the VM + context + emitter chunks with simulate.
@@ -54,7 +44,7 @@ export const PARTICLE_EMIT_WORKGROUP_SIZE = COMPUTE_SHADER_DEFAULT_GROUP_SIZE;
54
44
  *
55
45
  * @type {WebGPUStruct}
56
46
  */
57
- const EMIT_SETTINGS = WebGPUStruct.from({
47
+ export const EMIT_SETTINGS = WebGPUStruct.from({
58
48
  u_dt: f32,
59
49
  u_time: f32,
60
50
  u_frame: u32,
@@ -78,10 +68,6 @@ resources.createGroup()
78
68
  const body = CodeChunk.from(
79
69
  /* language=wgsl */
80
70
  `
81
- const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
82
- const PARTICLE_USER_WORD_START : u32 = ${PARTICLE_RECORD_USER_WORD_START}u;
83
- const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
84
- const PARTICLE_INSTRUCTION_WORDS : u32 = ${PARTICLE_VM_INSTRUCTION_WORDS}u;
85
71
  const COUNTER_ALIVE : u32 = ${PARTICLE_COUNTER.ALIVE}u;
86
72
  const COUNTER_DEAD : u32 = ${PARTICLE_COUNTER.DEAD}u;
87
73
 
@@ -89,77 +75,31 @@ const COUNTER_DEAD : u32 = ${PARTICLE_COUNTER.DEAD}u;
89
75
  fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
90
76
  let i = gid.x;
91
77
 
92
- // The scan's last inclusive sum is the number of particles born this frame. An empty list has
93
- // no last element to read; it also has no particles.
94
- let emitter_count = spawn_prefix.count;
95
- if (emitter_count == 0u) { return; }
96
- let total = spawn_prefix.elements[emitter_count - 1u];
97
- if (i >= total) { return; }
78
+ let assignment = particle_emit_assignment(&spawn_prefix.elements, spawn_prefix.count, i);
79
+ if (!assignment.valid) { return; }
98
80
 
99
- // The emitter is the first row whose inclusive sum exceeds i; its batch starts at the sum
100
- // before, which is the exclusive sum. Rows that spawned nothing this frame have equal sums and
101
- // the search steps over them.
102
- let emitter_row = lower_bound_branchless(&spawn_prefix.elements, i + 1u, emitter_count);
103
- var batch_start = 0u;
104
- if (emitter_row > 0u) {
105
- batch_start = spawn_prefix.elements[emitter_row - 1u];
106
- }
107
- let batch_size = spawn_prefix.elements[emitter_row] - batch_start;
108
-
109
- // SPAWN_FRACTION contract: this particle's place in its emitter's batch this frame, n / count,
110
- // for spreading a batch along a spawn curve.
111
- let spawn_fraction = f32(i - batch_start) / f32(batch_size);
112
-
113
- // Pop a free slot off the dead-list stack; drop the spawn if the pool is exhausted.
114
- //
115
- // The guard must catch WRAPPED values, not just 0: when many threads race an empty stack, the
116
- // first over-pop wraps the counter to 0xFFFFFFFF before its undo lands, and a concurrent thread
117
- // then observes a huge old value. Checking only ==0 would let it index dead[old-1] with garbage
118
- // and hand out a bogus slot, corrupting a live record. The dead count can never legitimately
119
- // exceed the pool capacity, so >settings.u_capacity identifies every wrapped state; each thread that
120
- // subtracted also adds back exactly once, so the counter converges to 0.
81
+ // Pop a free slot off the dead-list stack; drop the spawn if the pool is exhausted. The guard
82
+ // catches WRAPPED values, not just 0 — see chunk_particle_emit_step for why that matters.
121
83
  let old_dead = atomicSub(&counters[COUNTER_DEAD], 1u);
122
84
  if (old_dead == 0u || old_dead > settings.u_capacity) {
123
85
  atomicAdd(&counters[COUNTER_DEAD], 1u); // undo the over-pop
124
86
  return;
125
87
  }
126
88
  let slot = dead[old_dead - 1u];
127
- let record_base = slot * PARTICLE_RECORD_WORDS;
128
-
129
- let em = particle_emitter_read(&emitter_database, emitter_row);
130
- let node = scene_read_node(&scene_database, em.node);
131
89
 
132
- // Clear stale user state from a recycled slot (each write targets a distinct word).
133
- for (var w = PARTICLE_USER_WORD_START; w < PARTICLE_RECORD_WORDS; w = w + 1u) {
134
- pool[record_base + w] = 0u;
135
- }
136
- pool[record_base + PARTICLE_HEADER_EMITTER] = particle_header_pack(emitter_row, em.generation);
137
-
138
- particle_vm_reset();
139
- particle_setup_context(
140
- em, node, slot,
141
- settings.u_dt, settings.u_time,
142
- particle_emitter_age(&emitter_database, emitter_row),
143
- spawn_fraction, settings.u_frame,
144
- );
145
- particle_vm_execute(
146
- &program,
147
- em.init_offset * PARTICLE_INSTRUCTION_WORDS,
148
- em.init_count,
149
- em.constant_offset,
150
- &pool,
151
- record_base,
90
+ particle_emit_one(
91
+ &scene_database, &emitter_database, &program, &pool,
92
+ assignment.emitter_row, slot, assignment.spawn_fraction,
93
+ settings.u_dt, settings.u_time, settings.u_frame,
152
94
  );
153
95
 
154
96
  let a = atomicAdd(&counters[COUNTER_ALIVE], 1u);
155
97
  alive_out[a] = slot;
156
98
  }
157
99
  `, [
158
- chunk_particle_setup_context,
159
- chunk_particle_emitter_age,
100
+ chunk_particle_emit_step,
101
+ chunk_particle_vm_registers_fast,
160
102
  chunk_particle_curve_disabled,
161
- chunk_particle_header,
162
- chunk_lower_bound_branchless,
163
103
  ]);
164
104
 
165
105
  export const shader_particle_emit = ComputeShader.from({
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The emit pass over the WIDE register file — the fallback interpreter's spawn half.
3
+ *
4
+ * Same emission as {@link ./shader_particle_emit.js}, down to the shared
5
+ * {@link ./chunk_particle_emit_step.js}. It differs in the same way
6
+ * {@link ./shader_particle_simulate_wide.js} does: a bounded launch of
7
+ * {@link ../ParticleConstants.js PARTICLE_VM_WIDE_LAUNCH_LANES} lanes with a grid-stride loop, so
8
+ * the storage register file is sized by a constant rather than by how many particles happen to be
9
+ * born this frame.
10
+ *
11
+ * It therefore does not consume the indirect command the prefix scan produces for the fast pass. The
12
+ * scan's total is read in the shader as the loop bound instead, which is the same number from the
13
+ * same buffer — just used as a bound rather than as a dispatch size.
14
+ *
15
+ * The register file is indexed by launch lane, so it is reused across the loop's iterations. That is
16
+ * sound for the same reason it is never cleared: an INIT program writes a register before it reads
17
+ * it, so nothing carries between one newborn and the next. See
18
+ * {@link ../vm/chunk_particle_vm_registers_wide.js}.
19
+ *
20
+ * Emit's waves span emitters by construction, so — unlike simulate — there was never a wave-uniform
21
+ * decode here to lose.
22
+ *
23
+ * @type {ComputeShader}
24
+ */
25
+ /**
26
+ * Workgroups this pass dispatches. Constant: the launch does not depend on how many particles are
27
+ * born this frame.
28
+ * @type {number}
29
+ */
30
+ export const PARTICLE_EMIT_WIDE_WORKGROUP_COUNT: number;
31
+ export const shader_particle_emit_wide: ComputeShader;
32
+ import { ComputeShader } from "../../shader/ComputeShader.js";
33
+ //# sourceMappingURL=shader_particle_emit_wide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_particle_emit_wide.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_emit_wide.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;GAIG;AACH,iDAFU,MAAM,CAGiD;AAiEjE,sDAIG;8BA9G2B,+BAA+B"}
@@ -0,0 +1,114 @@
1
+ import { atomic_u32, f32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
+ import { COLLECTION_U32_STRUCT_READ } from "../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
4
+ import { ComputeShader } from "../../shader/ComputeShader.js";
5
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
6
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
+ import { PARTICLE_VM_WIDE_LAUNCH_LANES } from "../ParticleConstants.js";
8
+ import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
9
+ import { chunk_particle_vm_registers_wide } from "../vm/chunk_particle_vm_registers_wide.js";
10
+ import { chunk_particle_curve_disabled } from "./chunk_particle_curve_disabled.js";
11
+ import { chunk_particle_emit_step } from "./chunk_particle_emit_step.js";
12
+ import { EMIT_SETTINGS, PARTICLE_EMIT_WORKGROUP_SIZE } from "./shader_particle_emit.js";
13
+
14
+ /**
15
+ * The emit pass over the WIDE register file — the fallback interpreter's spawn half.
16
+ *
17
+ * Same emission as {@link ./shader_particle_emit.js}, down to the shared
18
+ * {@link ./chunk_particle_emit_step.js}. It differs in the same way
19
+ * {@link ./shader_particle_simulate_wide.js} does: a bounded launch of
20
+ * {@link ../ParticleConstants.js PARTICLE_VM_WIDE_LAUNCH_LANES} lanes with a grid-stride loop, so
21
+ * the storage register file is sized by a constant rather than by how many particles happen to be
22
+ * born this frame.
23
+ *
24
+ * It therefore does not consume the indirect command the prefix scan produces for the fast pass. The
25
+ * scan's total is read in the shader as the loop bound instead, which is the same number from the
26
+ * same buffer — just used as a bound rather than as a dispatch size.
27
+ *
28
+ * The register file is indexed by launch lane, so it is reused across the loop's iterations. That is
29
+ * sound for the same reason it is never cleared: an INIT program writes a register before it reads
30
+ * it, so nothing carries between one newborn and the next. See
31
+ * {@link ../vm/chunk_particle_vm_registers_wide.js}.
32
+ *
33
+ * Emit's waves span emitters by construction, so — unlike simulate — there was never a wave-uniform
34
+ * decode here to lose.
35
+ *
36
+ * @type {ComputeShader}
37
+ */
38
+
39
+ /**
40
+ * Workgroups this pass dispatches. Constant: the launch does not depend on how many particles are
41
+ * born this frame.
42
+ * @type {number}
43
+ */
44
+ export const PARTICLE_EMIT_WIDE_WORKGROUP_COUNT =
45
+ PARTICLE_VM_WIDE_LAUNCH_LANES / PARTICLE_EMIT_WORKGROUP_SIZE;
46
+
47
+ const resources = new ShaderResourceSetDescriptor();
48
+
49
+ resources.setImmediate('settings', EMIT_SETTINGS);
50
+
51
+ resources.createGroup()
52
+ .addStorageBuffer("scene_database", WebGPUArray.u32, false)
53
+ .addStorageBuffer("emitter_database", WebGPUArray.u32, false)
54
+ .addStorageBuffer("program", WebGPUArray.u32, false)
55
+ .addStorageBuffer("spawn_prefix", COLLECTION_U32_STRUCT_READ, false)
56
+ .addStorageBuffer("pool", WebGPUArray.u32, true)
57
+ .addStorageBuffer("alive_out", WebGPUArray.u32, true)
58
+ .addStorageBuffer("dead", WebGPUArray.u32, true)
59
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true)
60
+ .addStorageBuffer("vm_registers", WebGPUArray.from(f32), true);
61
+
62
+ const body = CodeChunk.from(
63
+ /* language=wgsl */
64
+ `
65
+ const COUNTER_ALIVE : u32 = ${PARTICLE_COUNTER.ALIVE}u;
66
+ const COUNTER_DEAD : u32 = ${PARTICLE_COUNTER.DEAD}u;
67
+
68
+ @compute @workgroup_size(${PARTICLE_EMIT_WORKGROUP_SIZE}, 1, 1)
69
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
70
+ // This invocation's column of the register file. The launch is exactly
71
+ // PARTICLE_VM_WIDE_LAUNCH_LANES wide, so gid.x is in range by construction.
72
+ particle_vm_bind_registers(gid.x);
73
+
74
+ // The scan's last inclusive sum is the number of particles born this frame — the bound this pass
75
+ // walks to, in place of the indirect dispatch the fast pass is sized by.
76
+ let emitter_count = spawn_prefix.count;
77
+ if (emitter_count == 0u) { return; }
78
+ let total = spawn_prefix.elements[emitter_count - 1u];
79
+
80
+ for (var i = gid.x; i < total; i = i + PARTICLE_VM_WIDE_LAUNCH_LANES) {
81
+ let assignment = particle_emit_assignment(&spawn_prefix.elements, emitter_count, i);
82
+ if (!assignment.valid) { continue; }
83
+
84
+ // Pop a free slot off the dead-list stack; drop the spawn if the pool is exhausted. The
85
+ // guard catches WRAPPED values, not just 0 — see chunk_particle_emit_step for why that
86
+ // matters.
87
+ let old_dead = atomicSub(&counters[COUNTER_DEAD], 1u);
88
+ if (old_dead == 0u || old_dead > settings.u_capacity) {
89
+ atomicAdd(&counters[COUNTER_DEAD], 1u); // undo the over-pop
90
+ continue;
91
+ }
92
+ let slot = dead[old_dead - 1u];
93
+
94
+ particle_emit_one(
95
+ &scene_database, &emitter_database, &program, &pool,
96
+ assignment.emitter_row, slot, assignment.spawn_fraction,
97
+ settings.u_dt, settings.u_time, settings.u_frame,
98
+ );
99
+
100
+ let a = atomicAdd(&counters[COUNTER_ALIVE], 1u);
101
+ alive_out[a] = slot;
102
+ }
103
+ }
104
+ `, [
105
+ chunk_particle_emit_step,
106
+ chunk_particle_vm_registers_wide,
107
+ chunk_particle_curve_disabled,
108
+ ]);
109
+
110
+ export const shader_particle_emit_wide = ComputeShader.from({
111
+ label: "Particle Emit (wide registers)",
112
+ resources,
113
+ body,
114
+ });
@@ -1,5 +1,13 @@
1
1
  export { PARTICLE_SIMULATE_WORKGROUP_SIZE };
2
+ /**
3
+ * Per-dispatch, 12 bytes, read-only — see shader_particle_emit for why the three travel
4
+ * together rather than as three uniforms.
5
+ *
6
+ * @type {WebGPUStruct}
7
+ */
8
+ export const SIMULATE_SETTINGS: WebGPUStruct;
2
9
  export const shader_particle_simulate: ComputeShader;
3
10
  import { PARTICLE_SIMULATE_WORKGROUP_SIZE } from "../ParticleConstants.js";
11
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
4
12
  import { ComputeShader } from "../../shader/ComputeShader.js";
5
13
  //# sourceMappingURL=shader_particle_simulate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":";AA+LA,qDAIG;iDAtLI,yBAAyB;8BATF,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":";AA0DA;;;;;GAKG;AACH,gCAFU,YAAY,CAMS;AAuD/B,qDAIG;iDAxH8C,yBAAyB;6BAJ7C,mCAAmC;8BAClC,+BAA+B"}
@@ -5,27 +5,27 @@ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
5
5
  import { ComputeShader } from "../../shader/ComputeShader.js";
6
6
  import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
7
7
  import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
8
- import {
9
- PARTICLE_RECORD_HEADER_EMITTER,
10
- PARTICLE_RECORD_WORD_COUNT,
11
- PARTICLE_SIMULATE_WORKGROUP_SIZE,
12
- PARTICLE_SIM_PAD_SLOT,
13
- PARTICLE_VM_INSTRUCTION_WORDS,
14
- } from "../ParticleConstants.js";
8
+ import { PARTICLE_SIMULATE_WORKGROUP_SIZE } from "../ParticleConstants.js";
15
9
  import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
16
- import { chunk_particle_header } from "../data/particle_header.js";
10
+ import { chunk_particle_vm_registers_fast } from "../vm/chunk_particle_vm_registers_fast.js";
17
11
  import { chunk_particle_curve_disabled } from "./chunk_particle_curve_disabled.js";
18
- import { chunk_particle_emitter_age } from "./chunk_particle_emitter_age.js";
19
- import { chunk_particle_setup_context } from "./chunk_particle_setup_context.js";
12
+ import { chunk_particle_simulate_step } from "./chunk_particle_simulate_step.js";
20
13
 
21
14
  /**
22
15
  * The particle simulate pass — Destiny-style single execution shader.
23
16
  *
24
- * One dispatch processes every live particle across every emitter. Per particle: read its owning
25
- * emitter, set up the VM context + RNG, run that emitter's compiled UPDATE program over the record,
26
- * then compact — killed particles are pushed back to the dead (free) list, survivors are appended to
27
- * the new alive list. There is exactly one pipeline regardless of how many distinct effects exist,
28
- * because behaviour is data (the bytecode program), not code.
17
+ * One dispatch processes every live particle across every emitter, one invocation each. Per
18
+ * particle: read its owning emitter, set up the VM context + RNG, run that emitter's compiled UPDATE
19
+ * program over the record, then compact — killed particles are pushed back to the dead (free) list,
20
+ * survivors are appended to the new alive list. There is exactly one pipeline regardless of how many
21
+ * distinct effects exist, because behaviour is data (the bytecode program), not code.
22
+ *
23
+ * The per-particle work is {@link ./chunk_particle_simulate_step.js}, shared with
24
+ * {@link ./shader_particle_simulate_wide.js}. What this file is, is the *fast* register backing plus
25
+ * the one-lane-per-particle dispatch that suits it. See
26
+ * {@link ../vm/chunk_particle_vm_registers_fast.js} for what "fast" costs and buys, and
27
+ * {@link ../ParticleConstants.js PARTICLE_VM_FAST_REGISTER_SLOTS} for when the system runs the other
28
+ * one instead.
29
29
  *
30
30
  * ## The input list
31
31
  *
@@ -33,23 +33,9 @@ import { chunk_particle_setup_context } from "./chunk_particle_setup_context.js"
33
33
  * pass (`../coherence/`) built at the end of last frame: the same pool slots, reordered so that
34
34
  * particles running one VM program sit together, each run padded out to a whole workgroup. That is
35
35
  * what keeps a wave from spanning two programs — and this shader leans on it rather than merely
36
- * benefiting from it: the section parameters are read from the wave's first lane
37
- * (`particle_wave_uniform` below), so a wave that held two programs would run one of them over the
38
- * other's particles. The coherence pass is part of this shader's correctness, not only of its speed.
39
- *
40
- * Padding entries carry {@link PARTICLE_SIM_PAD_SLOT} and are dropped BEFORE the compaction
41
- * atomics, so a padding lane never appends to the alive list and never pushes a slot onto the free
42
- * list — pushing the sentinel would put `0xffffffff` on the free list for a later emit to hand out
43
- * as a record base. Returning early is safe for the lanes that remain: padding only ever appears in
44
- * the tail of a bucket, and every real lane in that wave belongs to that one bucket, so the `switch`
45
- * the survivors execute is uniform regardless.
46
- *
47
- * ## Orphans
48
- *
49
- * A particle whose header generation is not its emitter row's current generation belongs to an
50
- * emitter that has been removed — the row is either zero-filled or already someone else's. It is
51
- * killed here, the frame the mismatch appears, before it can run a stranger's program or follow a
52
- * stranger's node. See `../data/particle_header.js`.
36
+ * benefiting from it: the section parameters are read from the wave's first lane, so a wave that
37
+ * held two programs would run one of them over the other's particles. The coherence pass is part of
38
+ * this shader's correctness, not only of its speed.
53
39
  *
54
40
  * ## Sizing
55
41
  *
@@ -76,7 +62,7 @@ export { PARTICLE_SIMULATE_WORKGROUP_SIZE };
76
62
  *
77
63
  * @type {WebGPUStruct}
78
64
  */
79
- const SIMULATE_SETTINGS = WebGPUStruct.from({
65
+ export const SIMULATE_SETTINGS = WebGPUStruct.from({
80
66
  u_dt: f32,
81
67
  u_time: f32,
82
68
  u_frame: u32,
@@ -98,33 +84,9 @@ resources.createGroup()
98
84
 
99
85
 
100
86
  const body = CodeChunk.from(/* language=wgsl */ `
101
- const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
102
- const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
103
- const PARTICLE_INSTRUCTION_WORDS : u32 = ${PARTICLE_VM_INSTRUCTION_WORDS}u;
104
87
  const COUNTER_ALIVE : u32 = ${PARTICLE_COUNTER.ALIVE}u;
105
88
  const COUNTER_DEAD : u32 = ${PARTICLE_COUNTER.DEAD}u;
106
89
  const COUNTER_ALIVE_IN : u32 = ${PARTICLE_COUNTER.ALIVE_IN}u;
107
- const PARTICLE_SIM_PAD_SLOT : u32 = ${PARTICLE_SIM_PAD_SLOT}u;
108
-
109
- // The value the wave's first live lane holds, in every lane.
110
- //
111
- // Everything that reaches the interpreter in one wave belongs to one bucket of sim_list: the
112
- // coherence pass grouped the list by program and padded each group to a whole workgroup, and the
113
- // padding and orphan lanes have left by the time a program runs. So the three numbers that pick a
114
- // section are the same in every lane. The compiler cannot see that — they come out of a table row
115
- // found through a per-lane header, which is as divergent as a value gets — and reading them from
116
- // the first lane is what tells it. The rest follows on its own: the instruction words are then
117
- // fetched through the scalar unit, the opcode switch branches on a scalar, and the register file is
118
- // indexed through M0 directly instead of through a waterfall loop over the lanes' indices. The VM
119
- // chunk is unchanged, and emit keeps its per-lane decode, because its waves span emitters.
120
- //
121
- // The uniformity diagnostic is off because the call sits behind per-lane early returns. That is the
122
- // situation the builtin is defined for — it reads the first ACTIVE lane — and the one WGSL's
123
- // analysis over-approximates.
124
- @diagnostic(off, subgroup_uniformity)
125
- fn particle_wave_uniform(value : u32) -> u32 {
126
- return subgroupBroadcastFirst(value);
127
- }
128
90
 
129
91
  @compute @workgroup_size(${PARTICLE_SIMULATE_WORKGROUP_SIZE}, 1, 1)
130
92
  fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
@@ -134,57 +96,27 @@ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
134
96
 
135
97
  let slot = sim_list[i];
136
98
 
137
- // A lane the coherence pass padded the bucket out with. Leave BEFORE the compaction atomics
138
- // below: appending here would put the sentinel on the alive or the free list, and the free list
139
- // would then hand 0xffffffff to an emit as a record base. The lanes that stay all belong to the
140
- // one bucket this wave covers, so their program — and the interpreter's switch — is uniform.
141
- if (slot == PARTICLE_SIM_PAD_SLOT) { return; }
142
-
143
- let record_base = slot * PARTICLE_RECORD_WORDS;
144
- let header = pool[record_base + PARTICLE_HEADER_EMITTER];
145
- let emitter_index = particle_header_emitter(header);
146
-
147
- let em = particle_emitter_read(&emitter_database, emitter_index);
148
-
149
- // An orphan: its emitter is gone and the row is free or somebody else's. Freed without running
150
- // a program — there is no program of its own left to run.
151
- var killed = particle_header_generation(header) != em.generation;
99
+ let verdict = particle_simulate_one(
100
+ &scene_database, &emitter_database, &program, &pool,
101
+ slot,
102
+ settings.u_dt, settings.u_time, settings.u_frame,
103
+ );
152
104
 
153
- if (!killed) {
154
- let node = scene_read_node(&scene_database, em.node);
155
-
156
- particle_vm_reset();
157
- particle_setup_context(
158
- em, node, slot,
159
- settings.u_dt, settings.u_time,
160
- particle_emitter_age(&emitter_database, emitter_index),
161
- 0.0, settings.u_frame,
162
- );
163
- particle_vm_execute(
164
- &program,
165
- particle_wave_uniform(em.update_offset) * PARTICLE_INSTRUCTION_WORDS,
166
- particle_wave_uniform(em.update_count),
167
- particle_wave_uniform(em.constant_offset),
168
- &pool,
169
- record_base,
170
- );
171
-
172
- killed = vm_killed;
173
- }
174
-
175
- if (killed) {
176
- let d = atomicAdd(&counters[COUNTER_DEAD], 1u);
177
- dead[d] = slot;
178
- } else {
105
+ // A padding lane's verdict is SKIP and books nothing. Appending it would put the padding
106
+ // sentinel on the alive or the free list, and the free list would then hand 0xffffffff to a
107
+ // later emit as a record base.
108
+ if (verdict == PARTICLE_SIM_ALIVE) {
179
109
  let a = atomicAdd(&counters[COUNTER_ALIVE], 1u);
180
110
  alive_out[a] = slot;
111
+ } else if (verdict == PARTICLE_SIM_KILLED) {
112
+ let d = atomicAdd(&counters[COUNTER_DEAD], 1u);
113
+ dead[d] = slot;
181
114
  }
182
115
  }
183
116
  `, [
184
- chunk_particle_setup_context,
185
- chunk_particle_emitter_age,
117
+ chunk_particle_simulate_step,
118
+ chunk_particle_vm_registers_fast,
186
119
  chunk_particle_curve_disabled,
187
- chunk_particle_header,
188
120
  ]);
189
121
 
190
122
  body.addExtension(WebGPUExtensionType.Subgroups);
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The simulate pass over the WIDE register file — the fallback interpreter.
3
+ *
4
+ * Same simulation as {@link ./shader_particle_simulate.js}, down to the shared
5
+ * {@link ./chunk_particle_simulate_step.js}: one dispatch, every live particle, the emitter's UPDATE
6
+ * program, compaction into the alive and free lists. Two things differ, and both follow from the
7
+ * register file living in a storage buffer.
8
+ *
9
+ * ## The launch is bounded, and the loop is grid-stride
10
+ *
11
+ * The fast pass runs one invocation per particle and sizes its dispatch indirectly from
12
+ * `counters[ALIVE_IN]`. This one cannot: it needs a register file per invocation in flight, so
13
+ * one-lane-per-particle would size the register buffer by pool capacity — a gigabyte at a million
14
+ * particles.
15
+ *
16
+ * So it launches exactly {@link ../ParticleConstants.js PARTICLE_VM_WIDE_LAUNCH_LANES} lanes,
17
+ * whatever the particle count, and each walks `sim_list` in strides of that. The register buffer is
18
+ * then sized by a constant this engine chose rather than by a number the pool decides. There is no
19
+ * indirect command and no CPU-side count: the launch is fixed, and the loop bound is still the
20
+ * on-GPU `counters[ALIVE_IN]` snapshot, read in the shader exactly as before. Every guarantee the
21
+ * fast pass's sizing comment describes holds here for the same reason.
22
+ *
23
+ * The stride is a whole number of workgroups, which is what keeps the coherence pass's bucketing
24
+ * intact: each iteration covers a workgroup-aligned span of `sim_list`, so a wave still sees one
25
+ * program and the wave-uniform section decode is still sound. That decode is worth keeping even
26
+ * here — it is what makes the instruction fetch and the opcode switch scalar. Only the register
27
+ * indexing goes per-lane, because in this backing it always is.
28
+ *
29
+ * ## Nine storage buffers
30
+ *
31
+ * The fast passes fit in the eight a stage gets by default; this one adds `vm_registers` and needs
32
+ * nine. That is inside what the engine already demands of an adapter — {@link
33
+ * ../../Renderer.js} refuses one offering fewer than ten — so it costs no new capability, but it is
34
+ * why the particle system's "everything fits in eight" note does not cover this shader.
35
+ *
36
+ * @type {ComputeShader}
37
+ */
38
+ /**
39
+ * Workgroups this pass dispatches. Constant: the launch does not depend on the particle count.
40
+ * @type {number}
41
+ */
42
+ export const PARTICLE_SIMULATE_WIDE_WORKGROUP_COUNT: number;
43
+ export const shader_particle_simulate_wide: ComputeShader;
44
+ import { ComputeShader } from "../../shader/ComputeShader.js";
45
+ //# sourceMappingURL=shader_particle_simulate_wide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_particle_simulate_wide.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;GAGG;AACH,qDAFU,MAAM,CAGqD;AA8DrE,0DAIG;8BAvH2B,+BAA+B"}