@woosh/meep-engine 3.12.0 → 3.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  3. package/src/core/geom/3d/shape/ConvexHullShape3D.js +41 -25
  4. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  5. package/src/core/geom/3d/shape/PosedShape3D.js +7 -2
  6. package/src/engine/graphics3/decal/GPUDecalRenderer.js +3 -3
  7. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  8. package/src/engine/graphics3/decal/shader_decal_composite.js +4 -2
  9. package/src/engine/graphics3/highlight/GPUHighlightRenderer.d.ts.map +1 -1
  10. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +2 -3
  11. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  12. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  13. package/src/shade/RENDERER_CONTRACT.md +2 -1
  14. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +18 -0
  15. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
  16. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +73 -0
  17. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +755 -0
  18. package/src/shade/device/ShadeGPUCommandContext.d.ts +10 -16
  19. package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
  20. package/src/shade/device/ShadeGPUCommandContext.js +801 -994
  21. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts +107 -0
  22. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts.map +1 -0
  23. package/src/shade/device/pass/ShadeGPUComputePassEncoder.js +222 -0
  24. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts +168 -0
  25. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts.map +1 -0
  26. package/src/shade/device/pass/ShadeGPURenderPassEncoder.js +317 -0
  27. package/src/shade/device/timing/GPUTimerArray.d.ts +4 -9
  28. package/src/shade/device/timing/GPUTimerArray.d.ts.map +1 -1
  29. package/src/shade/device/timing/GPUTimerArray.js +261 -289
  30. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +20 -2
  31. package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts +59 -0
  32. package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts.map +1 -0
  33. package/src/shade/device/timing/ShadeGPUContextProfiler.js +182 -0
  34. package/src/shade/device/timing/profile/GPUProfileSession.d.ts +4 -4
  35. package/src/shade/device/timing/profile/GPUProfileSession.js +4 -4
  36. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts.map +1 -1
  37. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.js +3 -1
  38. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.d.ts.map +1 -1
  39. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.js +3 -1
  40. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.d.ts.map +1 -1
  41. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.js +3 -1
  42. package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +2 -2
  43. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +2 -2
  44. package/src/shade/renderer/Renderer.d.ts +0 -6
  45. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  46. package/src/shade/renderer/Renderer.js +0 -29
  47. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  48. package/src/shade/renderer/animation/GPUAnimationManager.js +1 -3
  49. package/src/shade/renderer/animation/shader_animation_tick.d.ts.map +1 -1
  50. package/src/shade/renderer/animation/shader_animation_tick.js +128 -125
  51. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  52. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +8 -18
  53. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.d.ts.map +1 -1
  54. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.js +100 -98
  55. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.d.ts.map +1 -1
  56. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.js +215 -212
  57. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts +1 -1
  58. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts.map +1 -1
  59. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.js +135 -120
  60. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.d.ts.map +1 -1
  61. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.js +77 -75
  62. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
  63. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +375 -371
  64. package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +3 -3
  65. package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.js +1 -1
  66. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  67. package/src/shade/renderer/buffer/table/GPUDatabase.js +14 -19
  68. package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.d.ts.map +1 -1
  69. package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.js +7 -2
  70. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  71. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +325 -319
  72. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
  73. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +3 -1
  74. package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +1 -1
  75. package/src/shade/renderer/deferred/shader_tonemap_HDR.js +4 -1
  76. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts +2 -2
  77. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts.map +1 -1
  78. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  79. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +3 -3
  80. package/src/shade/renderer/fow/shader_fog_of_war.d.ts.map +1 -1
  81. package/src/shade/renderer/fow/shader_fog_of_war.js +3 -1
  82. package/src/shade/renderer/geometry/bvh/record_blas_refit.js +102 -102
  83. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts.map +1 -1
  84. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.js +125 -121
  85. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  86. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +766 -774
  87. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts.map +1 -1
  88. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.js +72 -69
  89. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  90. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +5 -10
  91. package/src/shade/renderer/geometry/sdf/shader_build_sdf.js +129 -129
  92. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts.map +1 -1
  93. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.js +5 -3
  94. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
  95. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +4 -1
  96. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.js +3 -1
  98. package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.d.ts.map +1 -1
  99. package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.js +114 -112
  100. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.d.ts.map +1 -1
  101. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.js +4 -1
  102. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.d.ts.map +1 -1
  103. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.js +187 -184
  104. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.js +4 -1
  106. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts.map +1 -1
  107. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.js +6 -8
  108. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +3 -1
  110. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.d.ts.map +1 -1
  111. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.js +3 -1
  112. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +3 -3
  113. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +3 -3
  114. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +217 -217
  115. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
  116. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +145 -142
  117. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
  118. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +87 -82
  119. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts.map +1 -1
  120. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.js +143 -140
  121. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts +2 -2
  122. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts.map +1 -1
  123. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.js +43 -8
  124. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  125. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +4 -5
  126. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
  127. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +88 -84
  128. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
  129. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +194 -191
  130. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  131. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +33 -69
  132. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  133. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +6 -1
  134. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +1 -1
  135. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.js +23 -7
  136. package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
  137. package/src/shade/renderer/light/environment/execute_filter_environment_map.js +1 -2
  138. package/src/shade/renderer/light/environment/shader_convolve_reflection_map.d.ts.map +1 -1
  139. package/src/shade/renderer/light/environment/shader_convolve_reflection_map.js +6 -1
  140. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.d.ts.map +1 -1
  141. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.js +234 -219
  142. package/src/shade/renderer/lightmap/bake/raster/shader_lightmap_to_viz_buffer.js +2 -2
  143. package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.js +191 -191
  144. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.d.ts.map +1 -1
  145. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.js +85 -82
  146. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  147. package/src/shade/renderer/particles/graph_particles.js +5 -3
  148. package/src/shade/renderer/particles/prototypeParticleSystem.js +3 -4
  149. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  150. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +132 -117
  151. package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
  152. package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +79 -77
  153. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  154. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +111 -99
  155. package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts.map +1 -1
  156. package/src/shade/renderer/particles/sort/shader_particle_sort.js +187 -158
  157. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
  158. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +7 -10
  159. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
  160. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +4 -1
  161. package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.d.ts.map +1 -1
  162. package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.js +3 -1
  163. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.d.ts.map +1 -1
  164. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +4 -2
  165. package/src/shade/renderer/postprocess/denoise/fragment_shader_denoise_ao.js +147 -147
  166. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.d.ts.map +1 -1
  167. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +121 -119
  168. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.d.ts.map +1 -1
  169. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +1 -2
  170. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.d.ts.map +1 -1
  171. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +4 -1
  172. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.d.ts.map +1 -1
  173. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +4 -1
  174. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.d.ts.map +1 -1
  175. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +4 -1
  176. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.d.ts.map +1 -1
  177. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +4 -1
  178. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.d.ts.map +1 -1
  179. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +2 -4
  180. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.d.ts.map +1 -1
  181. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +4 -1
  182. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.d.ts.map +1 -1
  183. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +4 -1
  184. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.d.ts.map +1 -1
  185. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.js +4 -1
  186. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.d.ts.map +1 -1
  187. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +269 -266
  188. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.d.ts.map +1 -1
  189. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +273 -270
  190. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.d.ts.map +1 -1
  191. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +4 -1
  192. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
  193. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +8 -11
  194. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.d.ts.map +1 -1
  195. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.js +5 -1
  196. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
  197. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +11 -8
  198. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
  199. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +7 -8
  200. package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.d.ts.map +1 -1
  201. package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.js +3 -1
  202. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  203. package/src/shade/renderer/postprocess/nss/shader_nss_concat.d.ts.map +1 -1
  204. package/src/shade/renderer/postprocess/nss/shader_nss_concat.js +70 -68
  205. package/src/shade/renderer/postprocess/ssr/depth_max_shader.d.ts.map +1 -1
  206. package/src/shade/renderer/postprocess/ssr/depth_max_shader.js +70 -68
  207. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts.map +1 -1
  208. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.js +3 -1
  209. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts.map +1 -1
  210. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.js +4 -1
  211. package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.d.ts.map +1 -1
  212. package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.js +103 -101
  213. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
  214. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +4 -2
  215. package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.d.ts.map +1 -1
  216. package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.js +3 -1
  217. package/src/shade/renderer/postprocess/taa/shader_taa.d.ts.map +1 -1
  218. package/src/shade/renderer/postprocess/taa/shader_taa.js +4 -1
  219. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +5 -5
  220. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  221. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +339 -341
  222. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
  223. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +114 -109
  224. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
  225. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +118 -115
  226. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  227. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +69 -65
  228. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +722 -722
  229. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  230. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +1 -9
  231. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  232. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +1 -6
  233. package/src/shade/renderer/restir/di/graph_restir_di.d.ts.map +1 -1
  234. package/src/shade/renderer/restir/di/graph_restir_di.js +2 -3
  235. package/src/shade/renderer/restir/di/graph_restir_di_denoise.d.ts.map +1 -1
  236. package/src/shade/renderer/restir/di/graph_restir_di_denoise.js +1 -2
  237. package/src/shade/renderer/restir/di/shader_restir_di_denoise.d.ts.map +1 -1
  238. package/src/shade/renderer/restir/di/shader_restir_di_denoise.js +139 -136
  239. package/src/shade/renderer/restir/di/shader_restir_di_resample.d.ts.map +1 -1
  240. package/src/shade/renderer/restir/di/shader_restir_di_resample.js +131 -129
  241. package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
  242. package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +101 -99
  243. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
  244. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +379 -383
  245. package/src/shade/renderer/scene/Mesh.d.ts.map +1 -1
  246. package/src/shade/renderer/scene/Mesh.js +4 -6
  247. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts.map +1 -1
  248. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +147 -144
  249. package/src/shade/renderer/shader/ComputeShader.d.ts +2 -2
  250. package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
  251. package/src/shade/renderer/shader/ComputeShader.js +14 -17
  252. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts +2 -2
  253. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
  254. package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +189 -189
  255. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  256. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +3 -1
  257. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +16 -7
  258. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  259. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +1342 -1326
  260. package/src/shade/renderer/shadow/map/Shadowmap.d.ts +13 -0
  261. package/src/shade/renderer/shadow/map/Shadowmap.d.ts.map +1 -1
  262. package/src/shade/renderer/shadow/map/Shadowmap.js +14 -0
  263. package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.d.ts +79 -0
  264. package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.d.ts.map +1 -0
  265. package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.js +196 -0
  266. package/src/shade/renderer/shadow/map/ShadowmapRegistry.d.ts +91 -0
  267. package/src/shade/renderer/shadow/map/ShadowmapRegistry.d.ts.map +1 -0
  268. package/src/shade/renderer/shadow/map/ShadowmapRegistry.js +156 -0
  269. package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.d.ts.map +1 -1
  270. package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.js +5 -1
  271. package/src/shade/renderer/shadow/ray/shader_shadow_upscale.d.ts.map +1 -1
  272. package/src/shade/renderer/shadow/ray/shader_shadow_upscale.js +3 -1
  273. package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +73 -73
  274. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
  275. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +151 -148
  276. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.d.ts.map +1 -1
  277. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +4 -2
  278. package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.d.ts.map +1 -1
  279. package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.js +18 -4
  280. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.d.ts.map +1 -1
  281. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +7 -8
  282. package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.d.ts.map +1 -1
  283. package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.js +6 -2
  284. package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.d.ts.map +1 -1
  285. package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.js +129 -127
  286. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts.map +1 -1
  287. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.js +5 -3
  288. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  289. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +2 -5
  290. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.d.ts.map +1 -1
  291. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +233 -231
  292. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  293. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +2 -4
  294. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  295. package/src/shade/wgsl/validate_wgsl_source.js +8 -3
  296. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts +0 -21
  297. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts.map +0 -1
  298. package/src/shade/device/timing/profile/make_profiling_pass_encoder.js +0 -114
  299. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts +0 -20
  300. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts.map +0 -1
  301. package/src/shade/device/timing/profile/parse_workgroup_size.js +0 -43
@@ -1,117 +1,132 @@
1
- import { atomic_u32, f32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
- import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
- import { ComputeShader } from "../../shader/ComputeShader.js";
4
- import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
- import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
6
- import {
7
- PARTICLE_RECORD_HEADER_EMITTER,
8
- PARTICLE_RECORD_USER_WORD_START,
9
- PARTICLE_RECORD_WORD_COUNT,
10
- PARTICLE_VM_INSTRUCTION_WORDS,
11
- } from "../ParticleConstants.js";
12
- import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
13
- import {
14
- SPAWN_REQUEST_EMITTER_MASK,
15
- SPAWN_REQUEST_FRACTION_MAX,
16
- SPAWN_REQUEST_FRACTION_SHIFT,
17
- } from "../runtime/spawn_request_encoding.js";
18
- import { chunk_particle_context, chunk_particle_curve_disabled } from "./chunk_particle_context.js";
19
-
20
- /**
21
- * The particle emit (spawn) pass.
22
- *
23
- * Input is a flat list of spawn requests (one packed emitter-index + batch-fraction per particle
24
- * to create; built by ParticleSpawnScheduler). Per request: pop a free slot from the dead
25
- * list, clear the record, stamp the owning emitter, run that emitter's compiled SPAWN program to
26
- * initialise the particle's user-defined state, then append the slot to the new alive list.
27
- *
28
- * Runs after simulate in the frame so newly born particles join the same alive list the survivors
29
- * were compacted into. Shares the VM + context + emitter chunks with simulate.
30
- *
31
- * @type {ComputeShader}
32
- */
33
-
34
- export const PARTICLE_EMIT_WORKGROUP_SIZE = 64;
35
-
36
- const resources = new ShaderResourceSetDescriptor();
37
- resources.createGroup()
38
- .addStorageBuffer("emitters", WebGPUArray.u32, false)
39
- .addStorageBuffer("program", WebGPUArray.u32, false)
40
- .addStorageBuffer("vm_constants", WebGPUArray.u32, false)
41
- .addStorageBuffer("pool", WebGPUArray.u32, true)
42
- .addStorageBuffer("spawn_requests", WebGPUArray.u32, false)
43
- .addStorageBuffer("alive_out", WebGPUArray.u32, true)
44
- .addStorageBuffer("dead", WebGPUArray.u32, true)
45
- .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true)
46
- .addUniform("u_dt", f32)
47
- .addUniform("u_time", f32)
48
- .addUniform("u_frame", u32)
49
- .addUniform("u_count", u32)
50
- .addUniform("u_capacity", u32);
51
-
52
- const body = CodeChunk.from(/* wgsl */ `
53
- const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
54
- const PARTICLE_USER_WORD_START : u32 = ${PARTICLE_RECORD_USER_WORD_START}u;
55
- const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
56
- const PARTICLE_INSTRUCTION_WORDS : u32 = ${PARTICLE_VM_INSTRUCTION_WORDS}u;
57
- const COUNTER_ALIVE : u32 = ${PARTICLE_COUNTER.ALIVE}u;
58
- const COUNTER_DEAD : u32 = ${PARTICLE_COUNTER.DEAD}u;
59
-
60
- @compute @workgroup_size(${PARTICLE_EMIT_WORKGROUP_SIZE}, 1, 1)
61
- fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
62
- let i = gid.x;
63
- if (i >= u_count) { return; }
64
-
65
- // Packed request: low 16 bits = emitter index, high 16 = batch fraction (see
66
- // spawn_request_encoding.js). The fraction is LOCAL to this emitter's batch this frame
67
- // (SPAWN_FRACTION contract: n / spawn_count), not the global request index / u_count.
68
- let request = spawn_requests[i];
69
- let emitter_index = request & ${SPAWN_REQUEST_EMITTER_MASK}u;
70
- let spawn_fraction = f32(request >> ${SPAWN_REQUEST_FRACTION_SHIFT}u) / ${SPAWN_REQUEST_FRACTION_MAX}.0;
71
-
72
- // Pop a free slot off the dead-list stack; drop the spawn if the pool is exhausted.
73
- //
74
- // The guard must catch WRAPPED values, not just 0: when many threads race an empty stack, the
75
- // first over-pop wraps the counter to 0xFFFFFFFF before its undo lands, and a concurrent thread
76
- // then observes a huge old value. Checking only ==0 would let it index dead[old-1] with garbage
77
- // and hand out a bogus slot, corrupting a live record. The dead count can never legitimately
78
- // exceed the pool capacity, so >u_capacity identifies every wrapped state; each thread that
79
- // subtracted also adds back exactly once, so the counter converges to 0.
80
- let old_dead = atomicSub(&counters[COUNTER_DEAD], 1u);
81
- if (old_dead == 0u || old_dead > u_capacity) {
82
- atomicAdd(&counters[COUNTER_DEAD], 1u); // undo the over-pop
83
- return;
84
- }
85
- let slot = dead[old_dead - 1u];
86
- let record_base = slot * PARTICLE_RECORD_WORDS;
87
-
88
- // Clear stale user state from a recycled slot (each write targets a distinct word).
89
- for (var w = PARTICLE_USER_WORD_START; w < PARTICLE_RECORD_WORDS; w = w + 1u) {
90
- pool[record_base + w] = 0u;
91
- }
92
- pool[record_base + PARTICLE_HEADER_EMITTER] = emitter_index;
93
-
94
- let em = particle_emitter_read(&emitters, emitter_index);
95
-
96
- particle_vm_reset();
97
- particle_setup_context(em, slot, u_dt, u_time, 0.0, spawn_fraction, u_frame);
98
- particle_vm_execute(
99
- &program,
100
- em.spawn_offset * PARTICLE_INSTRUCTION_WORDS,
101
- em.spawn_count,
102
- &vm_constants,
103
- em.constant_offset,
104
- &pool,
105
- record_base,
106
- );
107
-
108
- let a = atomicAdd(&counters[COUNTER_ALIVE], 1u);
109
- alive_out[a] = slot;
110
- }
111
- `, [chunk_particle_context, chunk_particle_curve_disabled]);
112
-
113
- export const shader_particle_emit = ComputeShader.from({
114
- label: "Particle Emit",
115
- resources,
116
- body,
117
- });
1
+ import { atomic_u32, f32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.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 {
8
+ PARTICLE_RECORD_HEADER_EMITTER,
9
+ PARTICLE_RECORD_USER_WORD_START,
10
+ PARTICLE_RECORD_WORD_COUNT,
11
+ PARTICLE_VM_INSTRUCTION_WORDS,
12
+ } from "../ParticleConstants.js";
13
+ import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
14
+ import {
15
+ SPAWN_REQUEST_EMITTER_MASK,
16
+ SPAWN_REQUEST_FRACTION_MAX,
17
+ SPAWN_REQUEST_FRACTION_SHIFT,
18
+ } from "../runtime/spawn_request_encoding.js";
19
+ import { chunk_particle_context, chunk_particle_curve_disabled } from "./chunk_particle_context.js";
20
+
21
+ /**
22
+ * The particle emit (spawn) pass.
23
+ *
24
+ * Input is a flat list of spawn requests (one packed emitter-index + batch-fraction per particle
25
+ * to create; built by ParticleSpawnScheduler). Per request: pop a free slot from the dead
26
+ * list, clear the record, stamp the owning emitter, run that emitter's compiled SPAWN program to
27
+ * initialise the particle's user-defined state, then append the slot to the new alive list.
28
+ *
29
+ * Runs after simulate in the frame so newly born particles join the same alive list the survivors
30
+ * were compacted into. Shares the VM + context + emitter chunks with simulate.
31
+ *
32
+ * @type {ComputeShader}
33
+ */
34
+
35
+ export const PARTICLE_EMIT_WORKGROUP_SIZE = 64;
36
+
37
+ /**
38
+ * Per-dispatch, 20 bytes, read-only.
39
+ *
40
+ * These were five separate uniforms, which meant five transient buffers, five staging copies and
41
+ * five bind group entries for twenty bytes of frame state. WGSL allows one immediate per entry
42
+ * point, so carrying them as immediate data means carrying them together.
43
+ *
44
+ * @type {WebGPUStruct}
45
+ */
46
+ const EMIT_SETTINGS = WebGPUStruct.from({
47
+ u_dt: f32,
48
+ u_time: f32,
49
+ u_frame: u32,
50
+ u_count: u32,
51
+ u_capacity: u32,
52
+ }, 'ParticleEmitSettings');
53
+
54
+ const resources = new ShaderResourceSetDescriptor();
55
+
56
+ resources.setImmediate('settings', EMIT_SETTINGS);
57
+
58
+ resources.createGroup()
59
+ .addStorageBuffer("emitters", WebGPUArray.u32, false)
60
+ .addStorageBuffer("program", WebGPUArray.u32, false)
61
+ .addStorageBuffer("vm_constants", WebGPUArray.u32, false)
62
+ .addStorageBuffer("pool", WebGPUArray.u32, true)
63
+ .addStorageBuffer("spawn_requests", WebGPUArray.u32, false)
64
+ .addStorageBuffer("alive_out", WebGPUArray.u32, true)
65
+ .addStorageBuffer("dead", WebGPUArray.u32, true)
66
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
67
+ const body = CodeChunk.from(/* wgsl */ `
68
+ const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
69
+ const PARTICLE_USER_WORD_START : u32 = ${PARTICLE_RECORD_USER_WORD_START}u;
70
+ const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
71
+ const PARTICLE_INSTRUCTION_WORDS : u32 = ${PARTICLE_VM_INSTRUCTION_WORDS}u;
72
+ const COUNTER_ALIVE : u32 = ${PARTICLE_COUNTER.ALIVE}u;
73
+ const COUNTER_DEAD : u32 = ${PARTICLE_COUNTER.DEAD}u;
74
+
75
+ @compute @workgroup_size(${PARTICLE_EMIT_WORKGROUP_SIZE}, 1, 1)
76
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
77
+ let i = gid.x;
78
+ if (i >= settings.u_count) { return; }
79
+
80
+ // Packed request: low 16 bits = emitter index, high 16 = batch fraction (see
81
+ // spawn_request_encoding.js). The fraction is LOCAL to this emitter's batch this frame
82
+ // (SPAWN_FRACTION contract: n / spawn_count), not the global request index / settings.u_count.
83
+ let request = spawn_requests[i];
84
+ let emitter_index = request & ${SPAWN_REQUEST_EMITTER_MASK}u;
85
+ let spawn_fraction = f32(request >> ${SPAWN_REQUEST_FRACTION_SHIFT}u) / ${SPAWN_REQUEST_FRACTION_MAX}.0;
86
+
87
+ // Pop a free slot off the dead-list stack; drop the spawn if the pool is exhausted.
88
+ //
89
+ // The guard must catch WRAPPED values, not just 0: when many threads race an empty stack, the
90
+ // first over-pop wraps the counter to 0xFFFFFFFF before its undo lands, and a concurrent thread
91
+ // then observes a huge old value. Checking only ==0 would let it index dead[old-1] with garbage
92
+ // and hand out a bogus slot, corrupting a live record. The dead count can never legitimately
93
+ // exceed the pool capacity, so >settings.u_capacity identifies every wrapped state; each thread that
94
+ // subtracted also adds back exactly once, so the counter converges to 0.
95
+ let old_dead = atomicSub(&counters[COUNTER_DEAD], 1u);
96
+ if (old_dead == 0u || old_dead > settings.u_capacity) {
97
+ atomicAdd(&counters[COUNTER_DEAD], 1u); // undo the over-pop
98
+ return;
99
+ }
100
+ let slot = dead[old_dead - 1u];
101
+ let record_base = slot * PARTICLE_RECORD_WORDS;
102
+
103
+ // Clear stale user state from a recycled slot (each write targets a distinct word).
104
+ for (var w = PARTICLE_USER_WORD_START; w < PARTICLE_RECORD_WORDS; w = w + 1u) {
105
+ pool[record_base + w] = 0u;
106
+ }
107
+ pool[record_base + PARTICLE_HEADER_EMITTER] = emitter_index;
108
+
109
+ let em = particle_emitter_read(&emitters, emitter_index);
110
+
111
+ particle_vm_reset();
112
+ particle_setup_context(em, slot, settings.u_dt, settings.u_time, 0.0, spawn_fraction, settings.u_frame);
113
+ particle_vm_execute(
114
+ &program,
115
+ em.spawn_offset * PARTICLE_INSTRUCTION_WORDS,
116
+ em.spawn_count,
117
+ &vm_constants,
118
+ em.constant_offset,
119
+ &pool,
120
+ record_base,
121
+ );
122
+
123
+ let a = atomicAdd(&counters[COUNTER_ALIVE], 1u);
124
+ alive_out[a] = slot;
125
+ }
126
+ `, [chunk_particle_context, chunk_particle_curve_disabled]);
127
+
128
+ export const shader_particle_emit = ComputeShader.from({
129
+ label: "Particle Emit",
130
+ resources,
131
+ body,
132
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_finalize.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_finalize.js"],"names":[],"mappings":"AA4BA,2DAWG;AAWH,2DAwBG;;8BAxE2B,+BAA+B;iDAIZ,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_finalize.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_finalize.js"],"names":[],"mappings":"AA4BA,2DAWG;AAaH,2DAwBG;;8BA1E2B,+BAA+B;iDAIZ,+BAA+B"}
@@ -1,77 +1,79 @@
1
- import { atomic_u32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
- import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
- import { ComputeShader } from "../../shader/ComputeShader.js";
4
- import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
- import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
6
- import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
7
- import { PARTICLE_SIMULATE_WORKGROUP_SIZE } from "./shader_particle_simulate.js";
8
-
9
- /**
10
- * Small housekeeping passes that keep the pipeline GPU-driven:
11
- *
12
- * - {@link shader_particle_reset_counters} — zero the alive / spawn / sorted counters at the top of
13
- * the frame (the dead count and the ALIVE_IN snapshot persist across frames).
14
- * - {@link shader_particle_build_indirect} — read the frame's final alive count and (a) snapshot it
15
- * into {@link PARTICLE_COUNTER.ALIVE_IN} — the exact input length for NEXT frame's simulate, (b)
16
- * write the indirect dispatch args next frame's simulate consumes, and (c) write the indirect draw
17
- * args for THIS frame's billboard render. Nothing round-trips to the CPU. Sizing the dispatch or
18
- * draw from a stale CPU readback instead is a correctness bug: when the alive count grows the tail
19
- * of the list is never simulated (slots leak into limbo), and when it shrinks stale entries beyond
20
- * the written range get re-simulated — a dead slot is pushed to the free list twice and later
21
- * popped twice, leaving two live particles sharing one record.
22
- */
23
-
24
- // --- reset ---
25
-
26
- const reset_resources = new ShaderResourceSetDescriptor();
27
- reset_resources.createGroup().addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
28
-
29
- export const shader_particle_reset_counters = ComputeShader.from({
30
- label: "Particle Reset Counters",
31
- resources: reset_resources,
32
- body: CodeChunk.from(/* wgsl */ `
33
- @compute @workgroup_size(1, 1, 1)
34
- fn main() {
35
- atomicStore(&counters[${PARTICLE_COUNTER.ALIVE}u], 0u);
36
- atomicStore(&counters[${PARTICLE_COUNTER.SPAWN}u], 0u);
37
- atomicStore(&counters[${PARTICLE_COUNTER.SORTED}u], 0u);
38
- }
39
- `),
40
- });
41
-
42
- // --- build indirect args ---
43
-
44
- const indirect_resources = new ShaderResourceSetDescriptor();
45
- indirect_resources.createGroup()
46
- .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true) // atomics require a read_write binding even for atomicLoad
47
- .addStorageBuffer("dispatch_args", WebGPUArray.u32, true) // {x,y,z}
48
- .addStorageBuffer("draw_args", WebGPUArray.u32, true) // {vertexCount, instanceCount, firstVertex, firstInstance}
49
- .addUniform("u_workgroup_size", u32);
50
-
51
- export const shader_particle_build_indirect = ComputeShader.from({
52
- label: "Particle Build Indirect",
53
- resources: indirect_resources,
54
- body: CodeChunk.from(/* wgsl */ `
55
- @compute @workgroup_size(1, 1, 1)
56
- fn main() {
57
- let alive = atomicLoad(&counters[${PARTICLE_COUNTER.ALIVE}u]);
58
-
59
- // Snapshot: this frame's final alive count is next frame's exact simulate input length.
60
- atomicStore(&counters[${PARTICLE_COUNTER.ALIVE_IN}u], alive);
61
-
62
- // Simulate dispatch (consumed NEXT frame): one thread per alive particle, whole workgroups.
63
- let groups = (alive + u_workgroup_size - 1u) / max(u_workgroup_size, 1u);
64
- dispatch_args[0] = groups;
65
- dispatch_args[1] = 1u;
66
- dispatch_args[2] = 1u;
67
-
68
- // Instanced billboard draw (consumed THIS frame): 6 verts per particle, one instance per alive.
69
- draw_args[0] = 6u;
70
- draw_args[1] = alive;
71
- draw_args[2] = 0u;
72
- draw_args[3] = 0u;
73
- }
74
- `),
75
- });
76
-
77
- export { PARTICLE_SIMULATE_WORKGROUP_SIZE };
1
+ import { atomic_u32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
+ import { ComputeShader } from "../../shader/ComputeShader.js";
4
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
6
+ import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
7
+ import { PARTICLE_SIMULATE_WORKGROUP_SIZE } from "./shader_particle_simulate.js";
8
+
9
+ /**
10
+ * Small housekeeping passes that keep the pipeline GPU-driven:
11
+ *
12
+ * - {@link shader_particle_reset_counters} — zero the alive / spawn / sorted counters at the top of
13
+ * the frame (the dead count and the ALIVE_IN snapshot persist across frames).
14
+ * - {@link shader_particle_build_indirect} — read the frame's final alive count and (a) snapshot it
15
+ * into {@link PARTICLE_COUNTER.ALIVE_IN} — the exact input length for NEXT frame's simulate, (b)
16
+ * write the indirect dispatch args next frame's simulate consumes, and (c) write the indirect draw
17
+ * args for THIS frame's billboard render. Nothing round-trips to the CPU. Sizing the dispatch or
18
+ * draw from a stale CPU readback instead is a correctness bug: when the alive count grows the tail
19
+ * of the list is never simulated (slots leak into limbo), and when it shrinks stale entries beyond
20
+ * the written range get re-simulated — a dead slot is pushed to the free list twice and later
21
+ * popped twice, leaving two live particles sharing one record.
22
+ */
23
+
24
+ // --- reset ---
25
+
26
+ const reset_resources = new ShaderResourceSetDescriptor();
27
+ reset_resources.createGroup().addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
28
+
29
+ export const shader_particle_reset_counters = ComputeShader.from({
30
+ label: "Particle Reset Counters",
31
+ resources: reset_resources,
32
+ body: CodeChunk.from(/* wgsl */ `
33
+ @compute @workgroup_size(1, 1, 1)
34
+ fn main() {
35
+ atomicStore(&counters[${PARTICLE_COUNTER.ALIVE}u], 0u);
36
+ atomicStore(&counters[${PARTICLE_COUNTER.SPAWN}u], 0u);
37
+ atomicStore(&counters[${PARTICLE_COUNTER.SORTED}u], 0u);
38
+ }
39
+ `),
40
+ });
41
+
42
+ // --- build indirect args ---
43
+
44
+ const indirect_resources = new ShaderResourceSetDescriptor();
45
+
46
+ // per-dispatch, four bytes, read-only: immediate data rather than a uniform buffer holding one u32
47
+ indirect_resources.setImmediate("u_workgroup_size", u32);
48
+ indirect_resources.createGroup()
49
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true) // atomics require a read_write binding even for atomicLoad
50
+ .addStorageBuffer("dispatch_args", WebGPUArray.u32, true) // {x,y,z}
51
+ .addStorageBuffer("draw_args", WebGPUArray.u32, true) // {vertexCount, instanceCount, firstVertex, firstInstance};
52
+
53
+ export const shader_particle_build_indirect = ComputeShader.from({
54
+ label: "Particle Build Indirect",
55
+ resources: indirect_resources,
56
+ body: CodeChunk.from(/* wgsl */ `
57
+ @compute @workgroup_size(1, 1, 1)
58
+ fn main() {
59
+ let alive = atomicLoad(&counters[${PARTICLE_COUNTER.ALIVE}u]);
60
+
61
+ // Snapshot: this frame's final alive count is next frame's exact simulate input length.
62
+ atomicStore(&counters[${PARTICLE_COUNTER.ALIVE_IN}u], alive);
63
+
64
+ // Simulate dispatch (consumed NEXT frame): one thread per alive particle, whole workgroups.
65
+ let groups = (alive + u_workgroup_size - 1u) / max(u_workgroup_size, 1u);
66
+ dispatch_args[0] = groups;
67
+ dispatch_args[1] = 1u;
68
+ dispatch_args[2] = 1u;
69
+
70
+ // Instanced billboard draw (consumed THIS frame): 6 verts per particle, one instance per alive.
71
+ draw_args[0] = 6u;
72
+ draw_args[1] = alive;
73
+ draw_args[2] = 0u;
74
+ draw_args[3] = 0u;
75
+ }
76
+ `),
77
+ });
78
+
79
+ export { PARTICLE_SIMULATE_WORKGROUP_SIZE };
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,+CAHU,aAAa,CAG4B;AA0DnD,qDAIG;8BAhG2B,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,+CAHU,aAAa,CAG4B;AAqEnD,qDAIG;8BA3G2B,+BAA+B"}