@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,99 +1,111 @@
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_WORD_COUNT,
9
- PARTICLE_VM_INSTRUCTION_WORDS,
10
- } from "../ParticleConstants.js";
11
- import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
12
- import { chunk_particle_context, chunk_particle_curve_disabled } from "./chunk_particle_context.js";
13
-
14
- /**
15
- * The particle simulate pass — Destiny-style single execution shader.
16
- *
17
- * One dispatch processes the entire alive list across every emitter. Per particle: read its owning
18
- * emitter, set up the VM context + RNG, run that emitter's compiled UPDATE program over the record,
19
- * then compact killed particles are pushed back to the dead (free) list, survivors are appended to
20
- * the new alive list. There is exactly one pipeline regardless of how many distinct effects exist,
21
- * because behaviour is data (the bytecode program), not code.
22
- *
23
- * The input length is read from `counters[ALIVE_IN]` — the previous frame's final alive count,
24
- * snapshotted on the GPU by the build-indirect pass NOT from a CPU uniform. A CPU-provided count
25
- * is inevitably stale (readback latency) and corrupts the pool: under-counting orphans the tail of
26
- * the alive list (slots leak into limbo), over-counting re-simulates stale entries and double-frees
27
- * their slots. Dispatch this shader with `dispatchWorkgroupsIndirect` using the args the
28
- * build-indirect pass wrote last frame, so thread count and bound agree by construction.
29
- *
30
- * All structured reads go through `array<u32>` for emulator-testability. Curve sampling uses the
31
- * pluggable `particle_vm_sample_curve` here the no-op provider; the feature swaps in the
32
- * animation-database-backed one.
33
- *
34
- * @type {ComputeShader}
35
- */
36
-
37
- export const PARTICLE_SIMULATE_WORKGROUP_SIZE = 64;
38
-
39
- const resources = new ShaderResourceSetDescriptor();
40
- resources.createGroup()
41
- .addStorageBuffer("emitters", WebGPUArray.u32, false)
42
- .addStorageBuffer("program", WebGPUArray.u32, false)
43
- .addStorageBuffer("vm_constants", WebGPUArray.u32, false)
44
- .addStorageBuffer("pool", WebGPUArray.u32, true)
45
- .addStorageBuffer("alive_in", WebGPUArray.u32, false)
46
- .addStorageBuffer("alive_out", WebGPUArray.u32, true)
47
- .addStorageBuffer("dead", WebGPUArray.u32, true)
48
- .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true)
49
- .addUniform("u_dt", f32)
50
- .addUniform("u_time", f32)
51
- .addUniform("u_frame", u32);
52
-
53
- const body = CodeChunk.from(/* wgsl */ `
54
- const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}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
- const COUNTER_ALIVE_IN : u32 = ${PARTICLE_COUNTER.ALIVE_IN}u;
60
-
61
- @compute @workgroup_size(${PARTICLE_SIMULATE_WORKGROUP_SIZE}, 1, 1)
62
- fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
63
- let i = gid.x;
64
- // The exact alive-list length, snapshotted on-GPU last frame — never a stale CPU value.
65
- if (i >= atomicLoad(&counters[COUNTER_ALIVE_IN])) { return; }
66
-
67
- let slot = alive_in[i];
68
- let record_base = slot * PARTICLE_RECORD_WORDS;
69
- let emitter_index = pool[record_base + PARTICLE_HEADER_EMITTER];
70
-
71
- let em = particle_emitter_read(&emitters, emitter_index);
72
-
73
- particle_vm_reset();
74
- particle_setup_context(em, slot, u_dt, u_time, 0.0, 0.0, u_frame);
75
- particle_vm_execute(
76
- &program,
77
- em.update_offset * PARTICLE_INSTRUCTION_WORDS,
78
- em.update_count,
79
- &vm_constants,
80
- em.constant_offset,
81
- &pool,
82
- record_base,
83
- );
84
-
85
- if (vm_killed) {
86
- let d = atomicAdd(&counters[COUNTER_DEAD], 1u);
87
- dead[d] = slot;
88
- } else {
89
- let a = atomicAdd(&counters[COUNTER_ALIVE], 1u);
90
- alive_out[a] = slot;
91
- }
92
- }
93
- `, [chunk_particle_context, chunk_particle_curve_disabled]);
94
-
95
- export const shader_particle_simulate = ComputeShader.from({
96
- label: "Particle Simulate",
97
- resources,
98
- body,
99
- });
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_WORD_COUNT,
10
+ PARTICLE_VM_INSTRUCTION_WORDS,
11
+ } from "../ParticleConstants.js";
12
+ import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
13
+ import { chunk_particle_context, chunk_particle_curve_disabled } from "./chunk_particle_context.js";
14
+
15
+ /**
16
+ * The particle simulate pass — Destiny-style single execution shader.
17
+ *
18
+ * One dispatch processes the entire alive list across every emitter. Per particle: read its owning
19
+ * emitter, set up the VM context + RNG, run that emitter's compiled UPDATE program over the record,
20
+ * then compact killed particles are pushed back to the dead (free) list, survivors are appended to
21
+ * the new alive list. There is exactly one pipeline regardless of how many distinct effects exist,
22
+ * because behaviour is data (the bytecode program), not code.
23
+ *
24
+ * The input length is read from `counters[ALIVE_IN]`the previous frame's final alive count,
25
+ * snapshotted on the GPU by the build-indirect pass NOT from a CPU uniform. A CPU-provided count
26
+ * is inevitably stale (readback latency) and corrupts the pool: under-counting orphans the tail of
27
+ * the alive list (slots leak into limbo), over-counting re-simulates stale entries and double-frees
28
+ * their slots. Dispatch this shader with `dispatchWorkgroupsIndirect` using the args the
29
+ * build-indirect pass wrote last frame, so thread count and bound agree by construction.
30
+ *
31
+ * All structured reads go through `array<u32>` for emulator-testability. Curve sampling uses the
32
+ * pluggable `particle_vm_sample_curve` — here the no-op provider; the feature swaps in the
33
+ * animation-database-backed one.
34
+ *
35
+ * @type {ComputeShader}
36
+ */
37
+
38
+ export const PARTICLE_SIMULATE_WORKGROUP_SIZE = 64;
39
+
40
+ /**
41
+ * Per-dispatch, 12 bytes, read-only — see shader_particle_emit for why the three travel
42
+ * together rather than as three uniforms.
43
+ *
44
+ * @type {WebGPUStruct}
45
+ */
46
+ const SIMULATE_SETTINGS = WebGPUStruct.from({
47
+ u_dt: f32,
48
+ u_time: f32,
49
+ u_frame: u32,
50
+ }, 'ParticleSimulateSettings');
51
+
52
+ const resources = new ShaderResourceSetDescriptor();
53
+
54
+ resources.setImmediate('settings', SIMULATE_SETTINGS);
55
+
56
+ resources.createGroup()
57
+ .addStorageBuffer("emitters", WebGPUArray.u32, false)
58
+ .addStorageBuffer("program", WebGPUArray.u32, false)
59
+ .addStorageBuffer("vm_constants", WebGPUArray.u32, false)
60
+ .addStorageBuffer("pool", WebGPUArray.u32, true)
61
+ .addStorageBuffer("alive_in", WebGPUArray.u32, false)
62
+ .addStorageBuffer("alive_out", WebGPUArray.u32, true)
63
+ .addStorageBuffer("dead", WebGPUArray.u32, true)
64
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
65
+ const body = CodeChunk.from(/* wgsl */ `
66
+ const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
67
+ const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
68
+ const PARTICLE_INSTRUCTION_WORDS : u32 = ${PARTICLE_VM_INSTRUCTION_WORDS}u;
69
+ const COUNTER_ALIVE : u32 = ${PARTICLE_COUNTER.ALIVE}u;
70
+ const COUNTER_DEAD : u32 = ${PARTICLE_COUNTER.DEAD}u;
71
+ const COUNTER_ALIVE_IN : u32 = ${PARTICLE_COUNTER.ALIVE_IN}u;
72
+
73
+ @compute @workgroup_size(${PARTICLE_SIMULATE_WORKGROUP_SIZE}, 1, 1)
74
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
75
+ let i = gid.x;
76
+ // The exact alive-list length, snapshotted on-GPU last frame — never a stale CPU value.
77
+ if (i >= atomicLoad(&counters[COUNTER_ALIVE_IN])) { return; }
78
+
79
+ let slot = alive_in[i];
80
+ let record_base = slot * PARTICLE_RECORD_WORDS;
81
+ let emitter_index = pool[record_base + PARTICLE_HEADER_EMITTER];
82
+
83
+ let em = particle_emitter_read(&emitters, emitter_index);
84
+
85
+ particle_vm_reset();
86
+ particle_setup_context(em, slot, settings.u_dt, settings.u_time, 0.0, 0.0, settings.u_frame);
87
+ particle_vm_execute(
88
+ &program,
89
+ em.update_offset * PARTICLE_INSTRUCTION_WORDS,
90
+ em.update_count,
91
+ &vm_constants,
92
+ em.constant_offset,
93
+ &pool,
94
+ record_base,
95
+ );
96
+
97
+ if (vm_killed) {
98
+ let d = atomicAdd(&counters[COUNTER_DEAD], 1u);
99
+ dead[d] = slot;
100
+ } else {
101
+ let a = atomicAdd(&counters[COUNTER_ALIVE], 1u);
102
+ alive_out[a] = slot;
103
+ }
104
+ }
105
+ `, [chunk_particle_context, chunk_particle_curve_disabled]);
106
+
107
+ export const shader_particle_simulate = ComputeShader.from({
108
+ label: "Particle Simulate",
109
+ resources,
110
+ body,
111
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_sort.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/sort/shader_particle_sort.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,8CAA+C;AAyB/C,uDAIG;AA+DH,2DAIG;AA4BH,yDAIG;8BA3J2B,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_sort.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/sort/shader_particle_sort.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,8CAA+C;AAkC/C,uDAIG;AAyEH,2DAIG;AAqCH,yDAIG;8BAvL2B,+BAA+B"}
@@ -1,158 +1,187 @@
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 { PARTICLE_RECORD_HEADER_EMITTER, PARTICLE_RECORD_WORD_COUNT } from "../ParticleConstants.js";
7
- import { EMITTER_ATTRIBUTE_ABSENT } from "../data/PARTICLE_EMITTER_LAYOUT.js";
8
- import { chunk_particle_emitter } from "../data/chunk_particle_emitter.js";
9
-
10
- /**
11
- * Depth-sort shaders. Three passes bracket a `csdldf` prefix scan:
12
- *
13
- * 0. {@link shader_particle_sort_reset} — every frame, write the histogram's `{count}` field
14
- * (= bucket count, which the csdldf scan reads to size itself) and zero the histogram bins and
15
- * the scatter cursor. Without this the scan consumes garbage counts and the scatter compounds
16
- * last frame's ranks the buffers are only zeroed by WebGPU on CREATION, not per frame.
17
- * 1. {@link shader_particle_sort_histogram} per alive particle, project its render position into
18
- * view space, quantise the depth into a back-to-front bucket (far first), store the bucket in
19
- * `keys`, and atomically bump the per-bucket `histogram`.
20
- * 2. graph_prefix_scan_csdldf turns the histogram into inclusive prefix sums.
21
- * 3. {@link shader_particle_sort_scatter} per particle, read its bucket, take the exclusive
22
- * offset from the scanned histogram and an atomic per-bucket rank, and write the particle's slot
23
- * into `sorted` at that position.
24
- *
25
- * The `csdldf` scan uses subgroup ops and isn't runnable under the emulator; the reset, histogram
26
- * and scatter passes are, and the CPU reference {@link ./particle_counting_sort.js} pins the
27
- * algorithm.
28
- */
29
-
30
- export const PARTICLE_SORT_WORKGROUP_SIZE = 64;
31
-
32
- // --- reset pass ---
33
-
34
- const reset_resources = new ShaderResourceSetDescriptor();
35
- reset_resources.createGroup()
36
- .addStorageBuffer("histogram", WebGPUArray.from(atomic_u32), true)
37
- .addStorageBuffer("cursor", WebGPUArray.from(atomic_u32), true)
38
- .addUniform("u_bucket_count", u32);
39
-
40
- const reset_body = CodeChunk.from(/* wgsl */ `
41
- @compute @workgroup_size(${PARTICLE_SORT_WORKGROUP_SIZE}, 1, 1)
42
- fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
43
- let i = gid.x;
44
- if (i == 0u) {
45
- // The {count, elements} header the csdldf scan sizes itself from.
46
- atomicStore(&histogram[0], u_bucket_count);
47
- }
48
- if (i < u_bucket_count) {
49
- atomicStore(&histogram[1u + i], 0u);
50
- atomicStore(&cursor[i], 0u);
51
- }
52
- }
53
- `);
54
-
55
- export const shader_particle_sort_reset = ComputeShader.from({
56
- label: "Particle Sort Reset",
57
- resources: reset_resources,
58
- body: reset_body,
59
- });
60
-
61
- const READ_MAT4 = /* wgsl */ `
62
- fn particle_read_mat4(m : ptr<storage, array<u32>, read>, o : u32) -> mat4x4<f32> {
63
- return mat4x4<f32>(
64
- vec4<f32>(bitcast<f32>((*m)[o + 0u]), bitcast<f32>((*m)[o + 1u]), bitcast<f32>((*m)[o + 2u]), bitcast<f32>((*m)[o + 3u])),
65
- vec4<f32>(bitcast<f32>((*m)[o + 4u]), bitcast<f32>((*m)[o + 5u]), bitcast<f32>((*m)[o + 6u]), bitcast<f32>((*m)[o + 7u])),
66
- vec4<f32>(bitcast<f32>((*m)[o + 8u]), bitcast<f32>((*m)[o + 9u]), bitcast<f32>((*m)[o + 10u]), bitcast<f32>((*m)[o + 11u])),
67
- vec4<f32>(bitcast<f32>((*m)[o + 12u]), bitcast<f32>((*m)[o + 13u]), bitcast<f32>((*m)[o + 14u]), bitcast<f32>((*m)[o + 15u])),
68
- );
69
- }
70
- `;
71
-
72
- // --- histogram pass ---
73
-
74
- const histogram_resources = new ShaderResourceSetDescriptor();
75
- histogram_resources.createGroup()
76
- .addStorageBuffer("emitters", WebGPUArray.u32, false)
77
- .addStorageBuffer("pool", WebGPUArray.u32, false)
78
- .addStorageBuffer("alive", WebGPUArray.u32, false)
79
- .addStorageBuffer("view_matrix", WebGPUArray.u32, false)
80
- .addStorageBuffer("keys", WebGPUArray.u32, true)
81
- .addStorageBuffer("histogram", WebGPUArray.from(atomic_u32), true)
82
- .addUniform("u_near", f32)
83
- .addUniform("u_far", f32)
84
- .addUniform("u_bucket_count", u32)
85
- .addUniform("u_count", u32);
86
-
87
- const histogram_body = CodeChunk.from(/* wgsl */ `
88
- const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
89
- const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
90
- const PARTICLE_ATTRIBUTE_ABSENT : u32 = ${EMITTER_ATTRIBUTE_ABSENT}u;
91
-
92
- ${READ_MAT4}
93
-
94
- @compute @workgroup_size(${PARTICLE_SORT_WORKGROUP_SIZE}, 1, 1)
95
- fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
96
- let i = gid.x;
97
- if (i >= u_count) { return; }
98
-
99
- let slot = alive[i];
100
- let base = slot * PARTICLE_RECORD_WORDS;
101
- let emitter_index = pool[base + PARTICLE_HEADER_EMITTER];
102
- let em = particle_emitter_read(&emitters, emitter_index);
103
-
104
- var world_pos = vec3<f32>(0.0);
105
- if (em.render_position != PARTICLE_ATTRIBUTE_ABSENT) {
106
- let o = base + em.render_position;
107
- world_pos = vec3<f32>(bitcast<f32>(pool[o]), bitcast<f32>(pool[o + 1u]), bitcast<f32>(pool[o + 2u]));
108
- }
109
-
110
- let view = particle_read_mat4(&view_matrix, 0u);
111
- let view_depth = -(view * vec4<f32>(world_pos, 1.0)).z;
112
-
113
- let t = (view_depth - u_near) / max(u_far - u_near, 1e-6);
114
- let clamped = clamp(1.0 - t, 0.0, 1.0);
115
- let bucket = min(u32(clamped * f32(u_bucket_count)), u_bucket_count - 1u);
116
-
117
- keys[i] = bucket;
118
- atomicAdd(&histogram[1u + bucket], 1u);
119
- }
120
- `, [chunk_particle_emitter]);
121
-
122
- export const shader_particle_sort_histogram = ComputeShader.from({
123
- label: "Particle Sort Histogram",
124
- resources: histogram_resources,
125
- body: histogram_body,
126
- });
127
-
128
- // --- scatter pass ---
129
-
130
- const scatter_resources = new ShaderResourceSetDescriptor();
131
- scatter_resources.createGroup()
132
- .addStorageBuffer("keys", WebGPUArray.u32, false)
133
- .addStorageBuffer("alive", WebGPUArray.u32, false)
134
- .addStorageBuffer("scanned", WebGPUArray.u32, false)
135
- .addStorageBuffer("cursor", WebGPUArray.from(atomic_u32), true)
136
- .addStorageBuffer("sorted", WebGPUArray.u32, true)
137
- .addUniform("u_count", u32);
138
-
139
- const scatter_body = CodeChunk.from(/* wgsl */ `
140
- @compute @workgroup_size(${PARTICLE_SORT_WORKGROUP_SIZE}, 1, 1)
141
- fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
142
- let i = gid.x;
143
- if (i >= u_count) { return; }
144
-
145
- let bucket = keys[i];
146
- // Exclusive offset = inclusive prefix sum up to bucket-1. With the count field at index 0 the
147
- // scanned inclusive value for bucket b lives at index (1+b), so bucket b-1 is at index b.
148
- let exclusive = select(0u, scanned[bucket], bucket > 0u);
149
- let rank = atomicAdd(&cursor[bucket], 1u);
150
- sorted[exclusive + rank] = alive[i];
151
- }
152
- `);
153
-
154
- export const shader_particle_sort_scatter = ComputeShader.from({
155
- label: "Particle Sort Scatter",
156
- resources: scatter_resources,
157
- body: scatter_body,
158
- });
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 { PARTICLE_RECORD_HEADER_EMITTER, PARTICLE_RECORD_WORD_COUNT } from "../ParticleConstants.js";
8
+ import { EMITTER_ATTRIBUTE_ABSENT } from "../data/PARTICLE_EMITTER_LAYOUT.js";
9
+ import { chunk_particle_emitter } from "../data/chunk_particle_emitter.js";
10
+
11
+ /**
12
+ * Depth-sort shaders. Three passes bracket a `csdldf` prefix scan:
13
+ *
14
+ * 0. {@link shader_particle_sort_reset} every frame, write the histogram's `{count}` field
15
+ * (= bucket count, which the csdldf scan reads to size itself) and zero the histogram bins and
16
+ * the scatter cursor. Without this the scan consumes garbage counts and the scatter compounds
17
+ * last frame's ranksthe buffers are only zeroed by WebGPU on CREATION, not per frame.
18
+ * 1. {@link shader_particle_sort_histogram} per alive particle, project its render position into
19
+ * view space, quantise the depth into a back-to-front bucket (far first), store the bucket in
20
+ * `keys`, and atomically bump the per-bucket `histogram`.
21
+ * 2. graph_prefix_scan_csdldf turns the histogram into inclusive prefix sums.
22
+ * 3. {@link shader_particle_sort_scatter} per particle, read its bucket, take the exclusive
23
+ * offset from the scanned histogram and an atomic per-bucket rank, and write the particle's slot
24
+ * into `sorted` at that position.
25
+ *
26
+ * The `csdldf` scan uses subgroup ops and isn't runnable under the emulator; the reset, histogram
27
+ * and scatter passes are, and the CPU reference {@link ./particle_counting_sort.js} pins the
28
+ * algorithm.
29
+ */
30
+
31
+ export const PARTICLE_SORT_WORKGROUP_SIZE = 64;
32
+
33
+ // --- reset pass ---
34
+
35
+ /**
36
+ * Per-dispatch, four bytes, read-only: immediate data rather than a uniform buffer.
37
+ *
38
+ * @type {WebGPUStruct}
39
+ */
40
+ const SORT_RESET_SETTINGS = WebGPUStruct.from({
41
+ u_bucket_count: u32,
42
+ }, 'ParticleSortResetSettings');
43
+
44
+ const reset_resources = new ShaderResourceSetDescriptor();
45
+
46
+ reset_resources.setImmediate('settings', SORT_RESET_SETTINGS);
47
+ reset_resources.createGroup()
48
+ .addStorageBuffer("histogram", WebGPUArray.from(atomic_u32), true)
49
+ .addStorageBuffer("cursor", WebGPUArray.from(atomic_u32), true);
50
+ const reset_body = CodeChunk.from(/* wgsl */ `
51
+ @compute @workgroup_size(${PARTICLE_SORT_WORKGROUP_SIZE}, 1, 1)
52
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
53
+ let i = gid.x;
54
+ if (i == 0u) {
55
+ // The {count, elements} header the csdldf scan sizes itself from.
56
+ atomicStore(&histogram[0], settings.u_bucket_count);
57
+ }
58
+ if (i < settings.u_bucket_count) {
59
+ atomicStore(&histogram[1u + i], 0u);
60
+ atomicStore(&cursor[i], 0u);
61
+ }
62
+ }
63
+ `);
64
+
65
+ export const shader_particle_sort_reset = ComputeShader.from({
66
+ label: "Particle Sort Reset",
67
+ resources: reset_resources,
68
+ body: reset_body,
69
+ });
70
+
71
+ const READ_MAT4 = /* wgsl */ `
72
+ fn particle_read_mat4(m : ptr<storage, array<u32>, read>, o : u32) -> mat4x4<f32> {
73
+ return mat4x4<f32>(
74
+ vec4<f32>(bitcast<f32>((*m)[o + 0u]), bitcast<f32>((*m)[o + 1u]), bitcast<f32>((*m)[o + 2u]), bitcast<f32>((*m)[o + 3u])),
75
+ vec4<f32>(bitcast<f32>((*m)[o + 4u]), bitcast<f32>((*m)[o + 5u]), bitcast<f32>((*m)[o + 6u]), bitcast<f32>((*m)[o + 7u])),
76
+ vec4<f32>(bitcast<f32>((*m)[o + 8u]), bitcast<f32>((*m)[o + 9u]), bitcast<f32>((*m)[o + 10u]), bitcast<f32>((*m)[o + 11u])),
77
+ vec4<f32>(bitcast<f32>((*m)[o + 12u]), bitcast<f32>((*m)[o + 13u]), bitcast<f32>((*m)[o + 14u]), bitcast<f32>((*m)[o + 15u])),
78
+ );
79
+ }
80
+ `;
81
+
82
+ // --- histogram pass ---
83
+
84
+ /**
85
+ * Per-dispatch, 16 bytes, read-only. Four uniforms meant four transient buffers per sort;
86
+ * WGSL allows one immediate per entry point, so they travel together.
87
+ *
88
+ * @type {WebGPUStruct}
89
+ */
90
+ const SORT_HISTOGRAM_SETTINGS = WebGPUStruct.from({
91
+ u_near: f32,
92
+ u_far: f32,
93
+ u_bucket_count: u32,
94
+ u_count: u32,
95
+ }, 'ParticleSortHistogramSettings');
96
+
97
+ const histogram_resources = new ShaderResourceSetDescriptor();
98
+
99
+ histogram_resources.setImmediate('settings', SORT_HISTOGRAM_SETTINGS);
100
+ histogram_resources.createGroup()
101
+ .addStorageBuffer("emitters", WebGPUArray.u32, false)
102
+ .addStorageBuffer("pool", WebGPUArray.u32, false)
103
+ .addStorageBuffer("alive", WebGPUArray.u32, false)
104
+ .addStorageBuffer("view_matrix", WebGPUArray.u32, false)
105
+ .addStorageBuffer("keys", WebGPUArray.u32, true)
106
+ .addStorageBuffer("histogram", WebGPUArray.from(atomic_u32), true);
107
+ const histogram_body = CodeChunk.from(/* wgsl */ `
108
+ const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
109
+ const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
110
+ const PARTICLE_ATTRIBUTE_ABSENT : u32 = ${EMITTER_ATTRIBUTE_ABSENT}u;
111
+
112
+ ${READ_MAT4}
113
+
114
+ @compute @workgroup_size(${PARTICLE_SORT_WORKGROUP_SIZE}, 1, 1)
115
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
116
+ let i = gid.x;
117
+ if (i >= settings.u_count) { return; }
118
+
119
+ let slot = alive[i];
120
+ let base = slot * PARTICLE_RECORD_WORDS;
121
+ let emitter_index = pool[base + PARTICLE_HEADER_EMITTER];
122
+ let em = particle_emitter_read(&emitters, emitter_index);
123
+
124
+ var world_pos = vec3<f32>(0.0);
125
+ if (em.render_position != PARTICLE_ATTRIBUTE_ABSENT) {
126
+ let o = base + em.render_position;
127
+ world_pos = vec3<f32>(bitcast<f32>(pool[o]), bitcast<f32>(pool[o + 1u]), bitcast<f32>(pool[o + 2u]));
128
+ }
129
+
130
+ let view = particle_read_mat4(&view_matrix, 0u);
131
+ let view_depth = -(view * vec4<f32>(world_pos, 1.0)).z;
132
+
133
+ let t = (view_depth - settings.u_near) / max(settings.u_far - settings.u_near, 1e-6);
134
+ let clamped = clamp(1.0 - t, 0.0, 1.0);
135
+ let bucket = min(u32(clamped * f32(settings.u_bucket_count)), settings.u_bucket_count - 1u);
136
+
137
+ keys[i] = bucket;
138
+ atomicAdd(&histogram[1u + bucket], 1u);
139
+ }
140
+ `, [chunk_particle_emitter]);
141
+
142
+ export const shader_particle_sort_histogram = ComputeShader.from({
143
+ label: "Particle Sort Histogram",
144
+ resources: histogram_resources,
145
+ body: histogram_body,
146
+ });
147
+
148
+ // --- scatter pass ---
149
+
150
+ /**
151
+ * Per-dispatch, four bytes, read-only: immediate data rather than a uniform buffer.
152
+ *
153
+ * @type {WebGPUStruct}
154
+ */
155
+ const SORT_SCATTER_SETTINGS = WebGPUStruct.from({
156
+ u_count: u32,
157
+ }, 'ParticleSortScatterSettings');
158
+
159
+ const scatter_resources = new ShaderResourceSetDescriptor();
160
+
161
+ scatter_resources.setImmediate('settings', SORT_SCATTER_SETTINGS);
162
+ scatter_resources.createGroup()
163
+ .addStorageBuffer("keys", WebGPUArray.u32, false)
164
+ .addStorageBuffer("alive", WebGPUArray.u32, false)
165
+ .addStorageBuffer("scanned", WebGPUArray.u32, false)
166
+ .addStorageBuffer("cursor", WebGPUArray.from(atomic_u32), true)
167
+ .addStorageBuffer("sorted", WebGPUArray.u32, true);
168
+ const scatter_body = CodeChunk.from(/* wgsl */ `
169
+ @compute @workgroup_size(${PARTICLE_SORT_WORKGROUP_SIZE}, 1, 1)
170
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
171
+ let i = gid.x;
172
+ if (i >= settings.u_count) { return; }
173
+
174
+ let bucket = keys[i];
175
+ // Exclusive offset = inclusive prefix sum up to bucket-1. With the count field at index 0 the
176
+ // scanned inclusive value for bucket b lives at index (1+b), so bucket b-1 is at index b.
177
+ let exclusive = select(0u, scanned[bucket], bucket > 0u);
178
+ let rank = atomicAdd(&cursor[bucket], 1u);
179
+ sorted[exclusive + rank] = alive[i];
180
+ }
181
+ `);
182
+
183
+ export const shader_particle_sort_scatter = ComputeShader.from({
184
+ label: "Particle Sort Scatter",
185
+ resources: scatter_resources,
186
+ body: scatter_body,
187
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"AccumulatingPathTracer.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;GAcG;AACH;IA8EI;;;OAGG;IACH,uCAgBC;IAhGD;;;;OAIG;IACH,kBAFU,MAAM,CAEO;IAEvB;;;;OAIG;IACH,wBAFU,MAAM,CAEc;IAE9B;;;;OAIG;IACH,eAFU,OAAO,CAEK;IA+NtB;;;;;;OAMG;IACH,yCAFa,MAAM,CA4JlB;;CACJ"}
1
+ {"version":3,"file":"AccumulatingPathTracer.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;GAcG;AACH;IA8EI;;;OAGG;IACH,uCAgBC;IAhGD;;;;OAIG;IACH,kBAFU,MAAM,CAEO;IAEvB;;;;OAIG;IACH,wBAFU,MAAM,CAEc;IAE9B;;;;OAIG;IACH,eAFU,OAAO,CAEK;IA+NtB;;;;;;OAMG;IACH,yCAFa,MAAM,CAyJlB;;CACJ"}
@@ -5,7 +5,7 @@ import { PerspectiveCamera } from "../../camera/PerspectiveCamera.js";
5
5
  import { GPUTextureContext } from "../../texture/GPUTextureContext.js";
6
6
  import { graph_flood_fill } from "./graph_flood_fill.js";
7
7
  import { graph_float32rgba_to_float16rgba } from "./graph_float32rgba_to_float16rgba.js";
8
- import { ACCUMULATING_RT_UNIFORMS_STRUCT, shader_accumulating_path_tracer } from "./shader_accumulating_path_tracer.js";
8
+ import { shader_accumulating_path_tracer } from "./shader_accumulating_path_tracer.js";
9
9
 
10
10
 
11
11
  const RGBA32FLOAT_BYTES_PER_PIXEL = 16;
@@ -359,15 +359,12 @@ export class AccumulatingPathTracer {
359
359
  [output_resource.width, output_resource.height, 1]
360
360
  );
361
361
 
362
- const settings = context.encoder.allocateTransientValueBuffer(
363
- ACCUMULATING_RT_UNIFORMS_STRUCT,
364
- {
365
- tile_offset: [tile_offset_x, tile_offset_y],
366
- tile_size: tile_size,
367
- random_seed: random_seed,
368
- alpha: alpha,
369
- }
370
- );
362
+ const settings = {
363
+ tile_offset: [tile_offset_x, tile_offset_y],
364
+ tile_size: tile_size,
365
+ random_seed: random_seed,
366
+ alpha: alpha,
367
+ };
371
368
 
372
369
  shader_accumulating_path_tracer.dispatch({
373
370
  encoder: context.encoder,
@@ -1 +1 @@
1
- {"version":3,"file":"shader_accumulating_path_tracer.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js"],"names":[],"mappings":"AAiBA,2DAKG;AA2EH,4DAIG;6BAnG0B,mCAAmC;8BAOlC,+BAA+B"}
1
+ {"version":3,"file":"shader_accumulating_path_tracer.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js"],"names":[],"mappings":"AAiBA,2DAKG;AA8EH,4DAIG;6BAtG0B,mCAAmC;8BAOlC,+BAA+B"}