@woosh/meep-engine 3.12.0 → 3.13.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 (285) hide show
  1. package/package.json +1 -1
  2. package/src/engine/graphics3/decal/GPUDecalRenderer.js +3 -3
  3. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  4. package/src/engine/graphics3/decal/shader_decal_composite.js +4 -2
  5. package/src/engine/graphics3/highlight/GPUHighlightRenderer.d.ts.map +1 -1
  6. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +2 -3
  7. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  8. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  9. package/src/shade/RENDERER_CONTRACT.md +2 -1
  10. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +18 -0
  11. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
  12. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +73 -0
  13. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +750 -0
  14. package/src/shade/device/ShadeGPUCommandContext.d.ts +10 -16
  15. package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
  16. package/src/shade/device/ShadeGPUCommandContext.js +801 -994
  17. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts +107 -0
  18. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts.map +1 -0
  19. package/src/shade/device/pass/ShadeGPUComputePassEncoder.js +222 -0
  20. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts +168 -0
  21. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts.map +1 -0
  22. package/src/shade/device/pass/ShadeGPURenderPassEncoder.js +317 -0
  23. package/src/shade/device/timing/GPUTimerArray.d.ts +4 -9
  24. package/src/shade/device/timing/GPUTimerArray.d.ts.map +1 -1
  25. package/src/shade/device/timing/GPUTimerArray.js +261 -289
  26. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +20 -2
  27. package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts +59 -0
  28. package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts.map +1 -0
  29. package/src/shade/device/timing/ShadeGPUContextProfiler.js +182 -0
  30. package/src/shade/device/timing/profile/GPUProfileSession.d.ts +4 -4
  31. package/src/shade/device/timing/profile/GPUProfileSession.js +4 -4
  32. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts.map +1 -1
  33. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.js +3 -1
  34. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.d.ts.map +1 -1
  35. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.js +3 -1
  36. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.d.ts.map +1 -1
  37. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.js +3 -1
  38. package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +2 -2
  39. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +2 -2
  40. package/src/shade/renderer/Renderer.d.ts +0 -6
  41. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  42. package/src/shade/renderer/Renderer.js +0 -29
  43. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  44. package/src/shade/renderer/animation/GPUAnimationManager.js +1 -3
  45. package/src/shade/renderer/animation/shader_animation_tick.d.ts.map +1 -1
  46. package/src/shade/renderer/animation/shader_animation_tick.js +128 -125
  47. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  48. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +8 -18
  49. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.d.ts.map +1 -1
  50. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.js +100 -98
  51. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.d.ts.map +1 -1
  52. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.js +215 -212
  53. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts +1 -1
  54. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts.map +1 -1
  55. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.js +135 -120
  56. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.d.ts.map +1 -1
  57. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.js +77 -75
  58. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
  59. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +375 -371
  60. package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +3 -3
  61. package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.js +1 -1
  62. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  63. package/src/shade/renderer/buffer/table/GPUDatabase.js +14 -19
  64. package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.d.ts.map +1 -1
  65. package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.js +7 -2
  66. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  67. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +325 -319
  68. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
  69. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +3 -1
  70. package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +1 -1
  71. package/src/shade/renderer/deferred/shader_tonemap_HDR.js +4 -1
  72. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts +2 -2
  73. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts.map +1 -1
  74. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  75. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +3 -3
  76. package/src/shade/renderer/fow/shader_fog_of_war.d.ts.map +1 -1
  77. package/src/shade/renderer/fow/shader_fog_of_war.js +3 -1
  78. package/src/shade/renderer/geometry/bvh/record_blas_refit.js +102 -102
  79. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts.map +1 -1
  80. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.js +125 -121
  81. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  82. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +766 -774
  83. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts.map +1 -1
  84. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.js +72 -69
  85. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  86. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +5 -10
  87. package/src/shade/renderer/geometry/sdf/shader_build_sdf.js +129 -129
  88. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts.map +1 -1
  89. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.js +5 -3
  90. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
  91. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +4 -1
  92. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.d.ts.map +1 -1
  93. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.js +3 -1
  94. package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.d.ts.map +1 -1
  95. package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.js +114 -112
  96. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.js +4 -1
  98. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.d.ts.map +1 -1
  99. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.js +187 -184
  100. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.d.ts.map +1 -1
  101. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.js +4 -1
  102. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts.map +1 -1
  103. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.js +6 -8
  104. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +3 -1
  106. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.d.ts.map +1 -1
  107. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.js +3 -1
  108. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +3 -3
  109. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +3 -3
  110. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +217 -217
  111. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
  112. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +145 -142
  113. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
  114. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +87 -82
  115. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts.map +1 -1
  116. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.js +143 -140
  117. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts +2 -2
  118. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts.map +1 -1
  119. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.js +43 -8
  120. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  121. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +4 -5
  122. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
  123. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +88 -84
  124. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
  125. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +194 -191
  126. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  127. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +33 -69
  128. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  129. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +6 -1
  130. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +1 -1
  131. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.js +23 -7
  132. package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
  133. package/src/shade/renderer/light/environment/execute_filter_environment_map.js +1 -2
  134. package/src/shade/renderer/light/environment/shader_convolve_reflection_map.d.ts.map +1 -1
  135. package/src/shade/renderer/light/environment/shader_convolve_reflection_map.js +6 -1
  136. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.d.ts.map +1 -1
  137. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.js +234 -219
  138. package/src/shade/renderer/lightmap/bake/raster/shader_lightmap_to_viz_buffer.js +2 -2
  139. package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.js +191 -191
  140. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.d.ts.map +1 -1
  141. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.js +85 -82
  142. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  143. package/src/shade/renderer/particles/graph_particles.js +5 -3
  144. package/src/shade/renderer/particles/prototypeParticleSystem.js +3 -4
  145. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  146. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +132 -117
  147. package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
  148. package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +79 -77
  149. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  150. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +111 -99
  151. package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts.map +1 -1
  152. package/src/shade/renderer/particles/sort/shader_particle_sort.js +187 -158
  153. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
  154. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +7 -10
  155. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
  156. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +4 -1
  157. package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.d.ts.map +1 -1
  158. package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.js +3 -1
  159. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.d.ts.map +1 -1
  160. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +4 -2
  161. package/src/shade/renderer/postprocess/denoise/fragment_shader_denoise_ao.js +147 -147
  162. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.d.ts.map +1 -1
  163. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +121 -119
  164. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.d.ts.map +1 -1
  165. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +1 -2
  166. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.d.ts.map +1 -1
  167. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +4 -1
  168. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.d.ts.map +1 -1
  169. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +4 -1
  170. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.d.ts.map +1 -1
  171. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +4 -1
  172. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.d.ts.map +1 -1
  173. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +4 -1
  174. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.d.ts.map +1 -1
  175. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +2 -4
  176. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.d.ts.map +1 -1
  177. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +4 -1
  178. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.d.ts.map +1 -1
  179. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +4 -1
  180. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.d.ts.map +1 -1
  181. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.js +4 -1
  182. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.d.ts.map +1 -1
  183. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +269 -266
  184. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.d.ts.map +1 -1
  185. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +273 -270
  186. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.d.ts.map +1 -1
  187. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +4 -1
  188. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
  189. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +8 -11
  190. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.d.ts.map +1 -1
  191. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.js +5 -1
  192. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
  193. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +11 -8
  194. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
  195. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +7 -8
  196. package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.d.ts.map +1 -1
  197. package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.js +3 -1
  198. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  199. package/src/shade/renderer/postprocess/nss/shader_nss_concat.d.ts.map +1 -1
  200. package/src/shade/renderer/postprocess/nss/shader_nss_concat.js +70 -68
  201. package/src/shade/renderer/postprocess/ssr/depth_max_shader.d.ts.map +1 -1
  202. package/src/shade/renderer/postprocess/ssr/depth_max_shader.js +70 -68
  203. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts.map +1 -1
  204. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.js +3 -1
  205. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts.map +1 -1
  206. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.js +4 -1
  207. package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.d.ts.map +1 -1
  208. package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.js +103 -101
  209. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
  210. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +4 -2
  211. package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.d.ts.map +1 -1
  212. package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.js +3 -1
  213. package/src/shade/renderer/postprocess/taa/shader_taa.d.ts.map +1 -1
  214. package/src/shade/renderer/postprocess/taa/shader_taa.js +4 -1
  215. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +5 -5
  216. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  217. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +339 -341
  218. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
  219. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +114 -109
  220. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
  221. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +118 -115
  222. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  223. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +69 -65
  224. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +722 -722
  225. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  226. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +1 -9
  227. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  228. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +1 -6
  229. package/src/shade/renderer/restir/di/graph_restir_di.d.ts.map +1 -1
  230. package/src/shade/renderer/restir/di/graph_restir_di.js +2 -3
  231. package/src/shade/renderer/restir/di/graph_restir_di_denoise.d.ts.map +1 -1
  232. package/src/shade/renderer/restir/di/graph_restir_di_denoise.js +1 -2
  233. package/src/shade/renderer/restir/di/shader_restir_di_denoise.d.ts.map +1 -1
  234. package/src/shade/renderer/restir/di/shader_restir_di_denoise.js +139 -136
  235. package/src/shade/renderer/restir/di/shader_restir_di_resample.d.ts.map +1 -1
  236. package/src/shade/renderer/restir/di/shader_restir_di_resample.js +131 -129
  237. package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
  238. package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +101 -99
  239. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
  240. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +379 -383
  241. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts.map +1 -1
  242. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +147 -144
  243. package/src/shade/renderer/shader/ComputeShader.d.ts +2 -2
  244. package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
  245. package/src/shade/renderer/shader/ComputeShader.js +14 -17
  246. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts +2 -2
  247. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
  248. package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +189 -189
  249. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  250. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +3 -1
  251. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  252. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +14 -18
  253. package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.d.ts.map +1 -1
  254. package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.js +5 -1
  255. package/src/shade/renderer/shadow/ray/shader_shadow_upscale.d.ts.map +1 -1
  256. package/src/shade/renderer/shadow/ray/shader_shadow_upscale.js +3 -1
  257. package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +73 -73
  258. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
  259. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +151 -148
  260. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.d.ts.map +1 -1
  261. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +4 -2
  262. package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.d.ts.map +1 -1
  263. package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.js +18 -4
  264. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.d.ts.map +1 -1
  265. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +7 -8
  266. package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.d.ts.map +1 -1
  267. package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.js +6 -2
  268. package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.d.ts.map +1 -1
  269. package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.js +129 -127
  270. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts.map +1 -1
  271. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.js +5 -3
  272. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  273. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +2 -5
  274. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.d.ts.map +1 -1
  275. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +233 -231
  276. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  277. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +2 -4
  278. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  279. package/src/shade/wgsl/validate_wgsl_source.js +8 -3
  280. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts +0 -21
  281. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts.map +0 -1
  282. package/src/shade/device/timing/profile/make_profiling_pass_encoder.js +0 -114
  283. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts +0 -20
  284. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts.map +0 -1
  285. 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"}