@woosh/meep-engine 3.12.0 → 3.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  3. package/src/core/geom/3d/shape/ConvexHullShape3D.js +41 -25
  4. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  5. package/src/core/geom/3d/shape/PosedShape3D.js +7 -2
  6. package/src/engine/graphics3/decal/GPUDecalRenderer.js +3 -3
  7. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  8. package/src/engine/graphics3/decal/shader_decal_composite.js +4 -2
  9. package/src/engine/graphics3/highlight/GPUHighlightRenderer.d.ts.map +1 -1
  10. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +2 -3
  11. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  12. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  13. package/src/shade/RENDERER_CONTRACT.md +2 -1
  14. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +18 -0
  15. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
  16. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +73 -0
  17. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +755 -0
  18. package/src/shade/device/ShadeGPUCommandContext.d.ts +10 -16
  19. package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
  20. package/src/shade/device/ShadeGPUCommandContext.js +801 -994
  21. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts +107 -0
  22. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts.map +1 -0
  23. package/src/shade/device/pass/ShadeGPUComputePassEncoder.js +222 -0
  24. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts +168 -0
  25. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts.map +1 -0
  26. package/src/shade/device/pass/ShadeGPURenderPassEncoder.js +317 -0
  27. package/src/shade/device/timing/GPUTimerArray.d.ts +4 -9
  28. package/src/shade/device/timing/GPUTimerArray.d.ts.map +1 -1
  29. package/src/shade/device/timing/GPUTimerArray.js +261 -289
  30. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +20 -2
  31. package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts +59 -0
  32. package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts.map +1 -0
  33. package/src/shade/device/timing/ShadeGPUContextProfiler.js +182 -0
  34. package/src/shade/device/timing/profile/GPUProfileSession.d.ts +4 -4
  35. package/src/shade/device/timing/profile/GPUProfileSession.js +4 -4
  36. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts.map +1 -1
  37. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.js +3 -1
  38. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.d.ts.map +1 -1
  39. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.js +3 -1
  40. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.d.ts.map +1 -1
  41. package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.js +3 -1
  42. package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +2 -2
  43. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +2 -2
  44. package/src/shade/renderer/Renderer.d.ts +0 -6
  45. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  46. package/src/shade/renderer/Renderer.js +0 -29
  47. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  48. package/src/shade/renderer/animation/GPUAnimationManager.js +1 -3
  49. package/src/shade/renderer/animation/shader_animation_tick.d.ts.map +1 -1
  50. package/src/shade/renderer/animation/shader_animation_tick.js +128 -125
  51. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  52. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +8 -18
  53. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.d.ts.map +1 -1
  54. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.js +100 -98
  55. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.d.ts.map +1 -1
  56. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.js +215 -212
  57. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts +1 -1
  58. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts.map +1 -1
  59. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.js +135 -120
  60. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.d.ts.map +1 -1
  61. package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.js +77 -75
  62. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
  63. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +375 -371
  64. package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +3 -3
  65. package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.js +1 -1
  66. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  67. package/src/shade/renderer/buffer/table/GPUDatabase.js +14 -19
  68. package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.d.ts.map +1 -1
  69. package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.js +7 -2
  70. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  71. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +325 -319
  72. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
  73. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +3 -1
  74. package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +1 -1
  75. package/src/shade/renderer/deferred/shader_tonemap_HDR.js +4 -1
  76. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts +2 -2
  77. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts.map +1 -1
  78. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  79. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +3 -3
  80. package/src/shade/renderer/fow/shader_fog_of_war.d.ts.map +1 -1
  81. package/src/shade/renderer/fow/shader_fog_of_war.js +3 -1
  82. package/src/shade/renderer/geometry/bvh/record_blas_refit.js +102 -102
  83. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts.map +1 -1
  84. package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.js +125 -121
  85. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  86. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +766 -774
  87. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts.map +1 -1
  88. package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.js +72 -69
  89. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  90. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +5 -10
  91. package/src/shade/renderer/geometry/sdf/shader_build_sdf.js +129 -129
  92. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts.map +1 -1
  93. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.js +5 -3
  94. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
  95. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +4 -1
  96. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.js +3 -1
  98. package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.d.ts.map +1 -1
  99. package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.js +114 -112
  100. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.d.ts.map +1 -1
  101. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.js +4 -1
  102. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.d.ts.map +1 -1
  103. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.js +187 -184
  104. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.js +4 -1
  106. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts.map +1 -1
  107. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.js +6 -8
  108. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +3 -1
  110. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.d.ts.map +1 -1
  111. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.js +3 -1
  112. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +3 -3
  113. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +3 -3
  114. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +217 -217
  115. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
  116. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +145 -142
  117. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
  118. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +87 -82
  119. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts.map +1 -1
  120. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.js +143 -140
  121. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts +2 -2
  122. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts.map +1 -1
  123. package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.js +43 -8
  124. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  125. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +4 -5
  126. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
  127. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +88 -84
  128. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
  129. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +194 -191
  130. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  131. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +33 -69
  132. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  133. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +6 -1
  134. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +1 -1
  135. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.js +23 -7
  136. package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
  137. package/src/shade/renderer/light/environment/execute_filter_environment_map.js +1 -2
  138. package/src/shade/renderer/light/environment/shader_convolve_reflection_map.d.ts.map +1 -1
  139. package/src/shade/renderer/light/environment/shader_convolve_reflection_map.js +6 -1
  140. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.d.ts.map +1 -1
  141. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.js +234 -219
  142. package/src/shade/renderer/lightmap/bake/raster/shader_lightmap_to_viz_buffer.js +2 -2
  143. package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.js +191 -191
  144. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.d.ts.map +1 -1
  145. package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.js +85 -82
  146. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  147. package/src/shade/renderer/particles/graph_particles.js +5 -3
  148. package/src/shade/renderer/particles/prototypeParticleSystem.js +3 -4
  149. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  150. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +132 -117
  151. package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
  152. package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +79 -77
  153. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  154. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +111 -99
  155. package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts.map +1 -1
  156. package/src/shade/renderer/particles/sort/shader_particle_sort.js +187 -158
  157. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
  158. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +7 -10
  159. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
  160. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +4 -1
  161. package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.d.ts.map +1 -1
  162. package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.js +3 -1
  163. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.d.ts.map +1 -1
  164. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +4 -2
  165. package/src/shade/renderer/postprocess/denoise/fragment_shader_denoise_ao.js +147 -147
  166. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.d.ts.map +1 -1
  167. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +121 -119
  168. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.d.ts.map +1 -1
  169. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +1 -2
  170. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.d.ts.map +1 -1
  171. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +4 -1
  172. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.d.ts.map +1 -1
  173. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +4 -1
  174. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.d.ts.map +1 -1
  175. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +4 -1
  176. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.d.ts.map +1 -1
  177. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +4 -1
  178. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.d.ts.map +1 -1
  179. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +2 -4
  180. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.d.ts.map +1 -1
  181. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +4 -1
  182. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.d.ts.map +1 -1
  183. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +4 -1
  184. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.d.ts.map +1 -1
  185. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.js +4 -1
  186. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.d.ts.map +1 -1
  187. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +269 -266
  188. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.d.ts.map +1 -1
  189. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +273 -270
  190. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.d.ts.map +1 -1
  191. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +4 -1
  192. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
  193. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +8 -11
  194. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.d.ts.map +1 -1
  195. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.js +5 -1
  196. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
  197. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +11 -8
  198. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
  199. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +7 -8
  200. package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.d.ts.map +1 -1
  201. package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.js +3 -1
  202. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  203. package/src/shade/renderer/postprocess/nss/shader_nss_concat.d.ts.map +1 -1
  204. package/src/shade/renderer/postprocess/nss/shader_nss_concat.js +70 -68
  205. package/src/shade/renderer/postprocess/ssr/depth_max_shader.d.ts.map +1 -1
  206. package/src/shade/renderer/postprocess/ssr/depth_max_shader.js +70 -68
  207. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts.map +1 -1
  208. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.js +3 -1
  209. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts.map +1 -1
  210. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.js +4 -1
  211. package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.d.ts.map +1 -1
  212. package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.js +103 -101
  213. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
  214. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +4 -2
  215. package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.d.ts.map +1 -1
  216. package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.js +3 -1
  217. package/src/shade/renderer/postprocess/taa/shader_taa.d.ts.map +1 -1
  218. package/src/shade/renderer/postprocess/taa/shader_taa.js +4 -1
  219. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +5 -5
  220. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  221. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +339 -341
  222. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
  223. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +114 -109
  224. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
  225. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +118 -115
  226. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  227. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +69 -65
  228. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +722 -722
  229. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  230. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +1 -9
  231. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  232. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +1 -6
  233. package/src/shade/renderer/restir/di/graph_restir_di.d.ts.map +1 -1
  234. package/src/shade/renderer/restir/di/graph_restir_di.js +2 -3
  235. package/src/shade/renderer/restir/di/graph_restir_di_denoise.d.ts.map +1 -1
  236. package/src/shade/renderer/restir/di/graph_restir_di_denoise.js +1 -2
  237. package/src/shade/renderer/restir/di/shader_restir_di_denoise.d.ts.map +1 -1
  238. package/src/shade/renderer/restir/di/shader_restir_di_denoise.js +139 -136
  239. package/src/shade/renderer/restir/di/shader_restir_di_resample.d.ts.map +1 -1
  240. package/src/shade/renderer/restir/di/shader_restir_di_resample.js +131 -129
  241. package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
  242. package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +101 -99
  243. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
  244. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +379 -383
  245. package/src/shade/renderer/scene/Mesh.d.ts.map +1 -1
  246. package/src/shade/renderer/scene/Mesh.js +4 -6
  247. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts.map +1 -1
  248. package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +147 -144
  249. package/src/shade/renderer/shader/ComputeShader.d.ts +2 -2
  250. package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
  251. package/src/shade/renderer/shader/ComputeShader.js +14 -17
  252. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts +2 -2
  253. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
  254. package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +189 -189
  255. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  256. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +3 -1
  257. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +16 -7
  258. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  259. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +1342 -1326
  260. package/src/shade/renderer/shadow/map/Shadowmap.d.ts +13 -0
  261. package/src/shade/renderer/shadow/map/Shadowmap.d.ts.map +1 -1
  262. package/src/shade/renderer/shadow/map/Shadowmap.js +14 -0
  263. package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.d.ts +79 -0
  264. package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.d.ts.map +1 -0
  265. package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.js +196 -0
  266. package/src/shade/renderer/shadow/map/ShadowmapRegistry.d.ts +91 -0
  267. package/src/shade/renderer/shadow/map/ShadowmapRegistry.d.ts.map +1 -0
  268. package/src/shade/renderer/shadow/map/ShadowmapRegistry.js +156 -0
  269. package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.d.ts.map +1 -1
  270. package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.js +5 -1
  271. package/src/shade/renderer/shadow/ray/shader_shadow_upscale.d.ts.map +1 -1
  272. package/src/shade/renderer/shadow/ray/shader_shadow_upscale.js +3 -1
  273. package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +73 -73
  274. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
  275. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +151 -148
  276. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.d.ts.map +1 -1
  277. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +4 -2
  278. package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.d.ts.map +1 -1
  279. package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.js +18 -4
  280. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.d.ts.map +1 -1
  281. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +7 -8
  282. package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.d.ts.map +1 -1
  283. package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.js +6 -2
  284. package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.d.ts.map +1 -1
  285. package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.js +129 -127
  286. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts.map +1 -1
  287. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.js +5 -3
  288. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  289. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +2 -5
  290. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.d.ts.map +1 -1
  291. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +233 -231
  292. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  293. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +2 -4
  294. package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
  295. package/src/shade/wgsl/validate_wgsl_source.js +8 -3
  296. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts +0 -21
  297. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts.map +0 -1
  298. package/src/shade/device/timing/profile/make_profiling_pass_encoder.js +0 -114
  299. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts +0 -20
  300. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts.map +0 -1
  301. package/src/shade/device/timing/profile/parse_workgroup_size.js +0 -43
@@ -1,212 +1,215 @@
1
- import { atomic_u32, u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
- import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
3
- import { GEOMETRY_METADATA_STRUCT } from "../../../geometry/GEOMETRY_METADATA_STRUCT.js";
4
- import { MESHLET_METADATA_STRUCT } from "../../../geometry/meshlet/encoding/MESHLET_METADATA_STRUCT.js";
5
- import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
6
- import { ComputeShader } from "../../../shader/ComputeShader.js";
7
- import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
8
- import { SKINNING_BINDING_STRUCT } from "../SKINNING_BINDING_STRUCT.js";
9
- import { chunk_aabb_atomic_f32 } from "./chunk_aabb_atomic_f32.js";
10
-
11
- /**
12
- * Workgroup size — also the per-meshlet vertex stride. One thread per
13
- * vertex slot per pass; threads loop by `WORKGROUP_SIZE` for meshlets
14
- * with `vertex_count > WORKGROUP_SIZE`.
15
- *
16
- * Matches the skinning compute shader's WG size so the reduction's
17
- * memory-access pattern is roughly analogous (sequential vertex reads).
18
- */
19
- export const WORKGROUP_SIZE = 64;
20
-
21
- // Field offsets resolved at module-load. `.pack()` on the structs
22
- // reorders fields by alignment, so reading offsets directly off the
23
- // struct is the only way to be sure these match what the rasterizer
24
- // expects to read back later.
25
- const MESHLET_BOUNDS_OFFSET_WORDS = MESHLET_METADATA_STRUCT.get('bounds_box').offset / 4;
26
- const MESHLET_ADDRESS_OFFSET_WORDS = MESHLET_METADATA_STRUCT.get('address').offset / 4;
27
- const MESHLET_VERTEX_COUNT_OFFSET_WORDS = MESHLET_METADATA_STRUCT.get('vertex_count').offset / 4;
28
- const MESHLET_PRIMITIVE_COUNT_OFFSET_WORDS = MESHLET_METADATA_STRUCT.get('primitive_count').offset / 4;
29
- const MESHLET_STRIDE_WORDS = MESHLET_METADATA_STRUCT.size / 4;
30
-
31
- const GEOMETRY_BBOX_OFFSET_WORDS = GEOMETRY_METADATA_STRUCT.get('bounding_box').offset / 4;
32
- const GEOMETRY_STRIDE_WORDS = GEOMETRY_METADATA_STRUCT.size / 4;
33
-
34
- const resources = new ShaderResourceSetDescriptor();
35
- resources.createGroup()
36
- // First-workgroup offset in this sub-dispatch (workgroup units).
37
- // One workgroup per pair, so this matches the skinning shader's
38
- // `dispatch_offset` semantic.
39
- .addUniform('dispatch_offset', u32)
40
- .addStorageBuffer('skinning_bindings', WebGPUArray.from(SKINNING_BINDING_STRUCT), false)
41
- .addStorageBuffer('dispatch_lookup', WebGPUArray.from(u32), false)
42
- // Clone vertex data: positions live at `address + index_section_size`
43
- // (see `chunk_meshlet_compute_attribute_section_offset`). Read-only
44
- // here — the skinning compute already wrote the deformed positions
45
- // before this pass runs.
46
- .addStorageBuffer('meshlet_data', WebGPUArray.from(u32), false)
47
- // Same buffer the rasterizer reads as typed structs, bound here as
48
- // a flat `atomic<u32>` array. We atomicLoad meshlet header fields
49
- // (address / vertex_count / primitive_count) and atomic-merge the
50
- // computed bounds into `bounds_box`.
51
- .addStorageBuffer('meshlet_metadata_atomic', WebGPUArray.from(atomic_u32), true)
52
- .addStorageBuffer('geometry_metadata_atomic', WebGPUArray.from(atomic_u32), true);
53
-
54
- const body = CodeChunk.from(
55
- //language=WGSL
56
- `
57
- const MESHLET_BOUNDS_OFFSET: u32 = ${MESHLET_BOUNDS_OFFSET_WORDS}u;
58
- const MESHLET_ADDRESS_OFFSET: u32 = ${MESHLET_ADDRESS_OFFSET_WORDS}u;
59
- const MESHLET_VERTEX_COUNT_OFFSET: u32 = ${MESHLET_VERTEX_COUNT_OFFSET_WORDS}u;
60
- const MESHLET_PRIMITIVE_COUNT_OFFSET: u32 = ${MESHLET_PRIMITIVE_COUNT_OFFSET_WORDS}u;
61
- const MESHLET_STRIDE: u32 = ${MESHLET_STRIDE_WORDS}u;
62
- const GEOMETRY_BBOX_OFFSET: u32 = ${GEOMETRY_BBOX_OFFSET_WORDS}u;
63
- const GEOMETRY_STRIDE: u32 = ${GEOMETRY_STRIDE_WORDS}u;
64
-
65
- // Workgroup-shared reduction storage. Each thread parks its
66
- // per-vertex-strip min/max here for tree reduction. Sized to the
67
- // workgroup width.
68
- var<workgroup> wg_min: array<vec3<f32>, ${WORKGROUP_SIZE}>;
69
- var<workgroup> wg_max: array<vec3<f32>, ${WORKGROUP_SIZE}>;
70
-
71
- @compute @workgroup_size(${WORKGROUP_SIZE},1,1)
72
- fn main(
73
- @builtin(workgroup_id) wg_id: vec3<u32>,
74
- @builtin(local_invocation_index) local_id: u32,
75
- ) {
76
- let pair_index = wg_id.x + dispatch_offset;
77
-
78
- let lookup_base = pair_index * 2u;
79
- let binding_index = dispatch_lookup[lookup_base];
80
- let meshlet_local = dispatch_lookup[lookup_base + 1u];
81
-
82
- let binding = skinning_bindings[binding_index];
83
- let clone_meshlet_abs = binding.clone_meshlet_metadata_offset + meshlet_local;
84
- let m_base_words = clone_meshlet_abs * MESHLET_STRIDE;
85
-
86
- // Meshlet header reads atomicLoad because the buffer is bound
87
- // atomic-typed. These values are stable across the pass (the
88
- // scatter pass only resets bounds_box, not the header), so reads
89
- // are uniform-control-flow safe.
90
- let address = atomicLoad(&meshlet_metadata_atomic[m_base_words + MESHLET_ADDRESS_OFFSET]);
91
- let primitive_count = atomicLoad(&meshlet_metadata_atomic[m_base_words + MESHLET_PRIMITIVE_COUNT_OFFSET]);
92
- let vertex_count = atomicLoad(&meshlet_metadata_atomic[m_base_words + MESHLET_VERTEX_COUNT_OFFSET]);
93
-
94
- // Attribute section base = address + index_section_size, where
95
- // index_section_size = ceil(primitive_count * 3 / 4) u32 words.
96
- // Position is the first attribute at offset 0 within the section,
97
- // stored as 3 contiguous f32s per vertex. Matches the skinning
98
- // shader's clone-write addressing.
99
- let index_section_size = (primitive_count * 3u + 3u) >> 2u;
100
- let attribute_section = address + index_section_size;
101
-
102
- // Per-thread min/max accumulators. WGSL disallows the const
103
- // expression \`bitcast<f32>(0x7F800000u)\` because the resulting
104
- // \`f32\` is not representable as a literal (it's ±inf). We use
105
- // the largest finite f32 instead for our purposes (vertex
106
- // positions, well-bounded in metres), it's effectively infinite:
107
- // any real vertex coordinate is many orders of magnitude
108
- // smaller, so the merge math is identical.
109
- //
110
- // Note that the storage sentinels in \`meshlet.bounds_box\` and
111
- // \`geometry.bounding_box\` ARE true ±inf the scatter pass
112
- // writes the u32 bit pattern directly via \`atomicStore\`, no
113
- // const-fold involved, and \`aabb_atomic_min_f32\` bitcasts
114
- // back to f32 at runtime where ±inf is a valid value.
115
- var thread_min = vec3<f32>( 3.4028234e38);
116
- var thread_max = vec3<f32>(-3.4028234e38);
117
-
118
- // Stride loop over the meshlet's vertex slots. Most meshlets fit
119
- // in a single WG_SIZE pass; larger ones cycle.
120
- var v: u32 = local_id;
121
- loop {
122
- if v >= vertex_count { break; }
123
- let pos_addr = attribute_section + v * 3u;
124
- let p = vec3<f32>(
125
- bitcast<f32>(meshlet_data[pos_addr]),
126
- bitcast<f32>(meshlet_data[pos_addr + 1u]),
127
- bitcast<f32>(meshlet_data[pos_addr + 2u]),
128
- );
129
- thread_min = min(thread_min, p);
130
- thread_max = max(thread_max, p);
131
- v = v + ${WORKGROUP_SIZE}u;
132
- }
133
-
134
- // Power-of-2 tree reduction in workgroup memory. WG_SIZE = 64 is
135
- // a power of two, so the standard halving stride works with no
136
- // tail handling. Subgroup ops would be a bit faster but require
137
- // the "subgroups" extension; this works on every device.
138
- wg_min[local_id] = thread_min;
139
- wg_max[local_id] = thread_max;
140
- workgroupBarrier();
141
-
142
- var stride: u32 = ${WORKGROUP_SIZE >>> 1}u;
143
- loop {
144
- if stride == 0u { break; }
145
- if local_id < stride {
146
- wg_min[local_id] = min(wg_min[local_id], wg_min[local_id + stride]);
147
- wg_max[local_id] = max(wg_max[local_id], wg_max[local_id + stride]);
148
- }
149
- workgroupBarrier();
150
- stride = stride >> 1u;
151
- }
152
-
153
- // Thread 0 owns the writes. Atomic-merge into both the meshlet's
154
- // own bounds_box (single contributor per meshlet — could be
155
- // atomicStore, but using min/max keeps the scatter's sentinel as
156
- // the identity element and means a re-run is idempotent) AND into
157
- // the binding's clone geometry's bounding_box (cross-workgroup
158
- // contention CAS-spin handles it).
159
- if local_id == 0u {
160
- let final_min = wg_min[0];
161
- let final_max = wg_max[0];
162
-
163
- let m_bounds_base = m_base_words + MESHLET_BOUNDS_OFFSET;
164
- aabb_atomic_min_f32(&meshlet_metadata_atomic[m_bounds_base + 0u], final_min.x);
165
- aabb_atomic_min_f32(&meshlet_metadata_atomic[m_bounds_base + 1u], final_min.y);
166
- aabb_atomic_min_f32(&meshlet_metadata_atomic[m_bounds_base + 2u], final_min.z);
167
- aabb_atomic_max_f32(&meshlet_metadata_atomic[m_bounds_base + 3u], final_max.x);
168
- aabb_atomic_max_f32(&meshlet_metadata_atomic[m_bounds_base + 4u], final_max.y);
169
- aabb_atomic_max_f32(&meshlet_metadata_atomic[m_bounds_base + 5u], final_max.z);
170
-
171
- let g_base = binding.clone_geometry_index * GEOMETRY_STRIDE + GEOMETRY_BBOX_OFFSET;
172
- aabb_atomic_min_f32(&geometry_metadata_atomic[g_base + 0u], final_min.x);
173
- aabb_atomic_min_f32(&geometry_metadata_atomic[g_base + 1u], final_min.y);
174
- aabb_atomic_min_f32(&geometry_metadata_atomic[g_base + 2u], final_min.z);
175
- aabb_atomic_max_f32(&geometry_metadata_atomic[g_base + 3u], final_max.x);
176
- aabb_atomic_max_f32(&geometry_metadata_atomic[g_base + 4u], final_max.y);
177
- aabb_atomic_max_f32(&geometry_metadata_atomic[g_base + 5u], final_max.z);
178
- }
179
- }
180
- `, [chunk_aabb_atomic_f32]);
181
-
182
- /**
183
- * Compute shader that reduces a clone meshlet's deformed vertex
184
- * positions to a tight AABB, atomic-writes the result to the meshlet's
185
- * `bounds_box`, and atomic-merges the same bounds into the owning
186
- * clone geometry's `bounding_box`.
187
- *
188
- * Workgroup-per-pair dispatch: one workgroup per (binding, meshlet)
189
- * row in `dispatch_lookup`. Each thread handles a stride of vertices,
190
- * the workgroup reduces via shared memory + tree halving, and thread 0
191
- * commits the result.
192
- *
193
- * The geometry-level merge is what lets the rasterizer's per-geometry
194
- * sphere/AABB culling use post-deformation bounds without a second
195
- * full pass — the sphere derive shader downstream just reads the
196
- * accumulated `bounding_box` and computes its surrounding sphere.
197
- *
198
- * Must run AFTER `shader_meshlet_apply_skinning` (which writes the
199
- * deformed positions this pass reads) and AFTER
200
- * `shader_meshlet_bounds_scatter` (which seeds the meshlet and
201
- * geometry bounds with ±inf sentinels).
202
- *
203
- * Pagination: with one workgroup per pair, the host splits into
204
- * multiple sub-dispatches when `total_pair_count >
205
- * maxComputeWorkgroupsPerDimension`. The `dispatch_offset` uniform
206
- * advances per sub-dispatch.
207
- */
208
- export const shader_meshlet_bounds_reduce = ComputeShader.from({
209
- label: "Skinning/MeshletBoundsReduce",
210
- resources,
211
- body,
212
- });
1
+ import { atomic_u32, u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
3
+ import { GEOMETRY_METADATA_STRUCT } from "../../../geometry/GEOMETRY_METADATA_STRUCT.js";
4
+ import { MESHLET_METADATA_STRUCT } from "../../../geometry/meshlet/encoding/MESHLET_METADATA_STRUCT.js";
5
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
6
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
7
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
8
+ import { SKINNING_BINDING_STRUCT } from "../SKINNING_BINDING_STRUCT.js";
9
+ import { chunk_aabb_atomic_f32 } from "./chunk_aabb_atomic_f32.js";
10
+
11
+ /**
12
+ * Workgroup size — also the per-meshlet vertex stride. One thread per
13
+ * vertex slot per pass; threads loop by `WORKGROUP_SIZE` for meshlets
14
+ * with `vertex_count > WORKGROUP_SIZE`.
15
+ *
16
+ * Matches the skinning compute shader's WG size so the reduction's
17
+ * memory-access pattern is roughly analogous (sequential vertex reads).
18
+ */
19
+ export const WORKGROUP_SIZE = 64;
20
+
21
+ // Field offsets resolved at module-load. `.pack()` on the structs
22
+ // reorders fields by alignment, so reading offsets directly off the
23
+ // struct is the only way to be sure these match what the rasterizer
24
+ // expects to read back later.
25
+ const MESHLET_BOUNDS_OFFSET_WORDS = MESHLET_METADATA_STRUCT.get('bounds_box').offset / 4;
26
+ const MESHLET_ADDRESS_OFFSET_WORDS = MESHLET_METADATA_STRUCT.get('address').offset / 4;
27
+ const MESHLET_VERTEX_COUNT_OFFSET_WORDS = MESHLET_METADATA_STRUCT.get('vertex_count').offset / 4;
28
+ const MESHLET_PRIMITIVE_COUNT_OFFSET_WORDS = MESHLET_METADATA_STRUCT.get('primitive_count').offset / 4;
29
+ const MESHLET_STRIDE_WORDS = MESHLET_METADATA_STRUCT.size / 4;
30
+
31
+ const GEOMETRY_BBOX_OFFSET_WORDS = GEOMETRY_METADATA_STRUCT.get('bounding_box').offset / 4;
32
+ const GEOMETRY_STRIDE_WORDS = GEOMETRY_METADATA_STRUCT.size / 4;
33
+
34
+ const resources = new ShaderResourceSetDescriptor();
35
+
36
+ // per-dispatch, four bytes, read-only: immediate data rather than a uniform buffer, allocated once
37
+ // per paginated sub-dispatch
38
+ resources.setImmediate("dispatch_offset", u32);
39
+ resources.createGroup()
40
+ // First-workgroup offset in this sub-dispatch (workgroup units).
41
+ // One workgroup per pair, so this matches the skinning shader's
42
+ // `dispatch_offset` semantic.
43
+ .addStorageBuffer('skinning_bindings', WebGPUArray.from(SKINNING_BINDING_STRUCT), false)
44
+ .addStorageBuffer('dispatch_lookup', WebGPUArray.from(u32), false)
45
+ // Clone vertex data: positions live at `address + index_section_size`
46
+ // (see `chunk_meshlet_compute_attribute_section_offset`). Read-only
47
+ // here the skinning compute already wrote the deformed positions
48
+ // before this pass runs.
49
+ .addStorageBuffer('meshlet_data', WebGPUArray.from(u32), false)
50
+ // Same buffer the rasterizer reads as typed structs, bound here as
51
+ // a flat `atomic<u32>` array. We atomicLoad meshlet header fields
52
+ // (address / vertex_count / primitive_count) and atomic-merge the
53
+ // computed bounds into `bounds_box`.
54
+ .addStorageBuffer('meshlet_metadata_atomic', WebGPUArray.from(atomic_u32), true)
55
+ .addStorageBuffer('geometry_metadata_atomic', WebGPUArray.from(atomic_u32), true);
56
+
57
+ const body = CodeChunk.from(
58
+ //language=WGSL
59
+ `
60
+ const MESHLET_BOUNDS_OFFSET: u32 = ${MESHLET_BOUNDS_OFFSET_WORDS}u;
61
+ const MESHLET_ADDRESS_OFFSET: u32 = ${MESHLET_ADDRESS_OFFSET_WORDS}u;
62
+ const MESHLET_VERTEX_COUNT_OFFSET: u32 = ${MESHLET_VERTEX_COUNT_OFFSET_WORDS}u;
63
+ const MESHLET_PRIMITIVE_COUNT_OFFSET: u32 = ${MESHLET_PRIMITIVE_COUNT_OFFSET_WORDS}u;
64
+ const MESHLET_STRIDE: u32 = ${MESHLET_STRIDE_WORDS}u;
65
+ const GEOMETRY_BBOX_OFFSET: u32 = ${GEOMETRY_BBOX_OFFSET_WORDS}u;
66
+ const GEOMETRY_STRIDE: u32 = ${GEOMETRY_STRIDE_WORDS}u;
67
+
68
+ // Workgroup-shared reduction storage. Each thread parks its
69
+ // per-vertex-strip min/max here for tree reduction. Sized to the
70
+ // workgroup width.
71
+ var<workgroup> wg_min: array<vec3<f32>, ${WORKGROUP_SIZE}>;
72
+ var<workgroup> wg_max: array<vec3<f32>, ${WORKGROUP_SIZE}>;
73
+
74
+ @compute @workgroup_size(${WORKGROUP_SIZE},1,1)
75
+ fn main(
76
+ @builtin(workgroup_id) wg_id: vec3<u32>,
77
+ @builtin(local_invocation_index) local_id: u32,
78
+ ) {
79
+ let pair_index = wg_id.x + dispatch_offset;
80
+
81
+ let lookup_base = pair_index * 2u;
82
+ let binding_index = dispatch_lookup[lookup_base];
83
+ let meshlet_local = dispatch_lookup[lookup_base + 1u];
84
+
85
+ let binding = skinning_bindings[binding_index];
86
+ let clone_meshlet_abs = binding.clone_meshlet_metadata_offset + meshlet_local;
87
+ let m_base_words = clone_meshlet_abs * MESHLET_STRIDE;
88
+
89
+ // Meshlet header reads — atomicLoad because the buffer is bound
90
+ // atomic-typed. These values are stable across the pass (the
91
+ // scatter pass only resets bounds_box, not the header), so reads
92
+ // are uniform-control-flow safe.
93
+ let address = atomicLoad(&meshlet_metadata_atomic[m_base_words + MESHLET_ADDRESS_OFFSET]);
94
+ let primitive_count = atomicLoad(&meshlet_metadata_atomic[m_base_words + MESHLET_PRIMITIVE_COUNT_OFFSET]);
95
+ let vertex_count = atomicLoad(&meshlet_metadata_atomic[m_base_words + MESHLET_VERTEX_COUNT_OFFSET]);
96
+
97
+ // Attribute section base = address + index_section_size, where
98
+ // index_section_size = ceil(primitive_count * 3 / 4) u32 words.
99
+ // Position is the first attribute at offset 0 within the section,
100
+ // stored as 3 contiguous f32s per vertex. Matches the skinning
101
+ // shader's clone-write addressing.
102
+ let index_section_size = (primitive_count * 3u + 3u) >> 2u;
103
+ let attribute_section = address + index_section_size;
104
+
105
+ // Per-thread min/max accumulators. WGSL disallows the const
106
+ // expression \`bitcast<f32>(0x7F800000u)\` because the resulting
107
+ // \`f32\` is not representable as a literal (it's ±inf). We use
108
+ // the largest finite f32 instead for our purposes (vertex
109
+ // positions, well-bounded in metres), it's effectively infinite:
110
+ // any real vertex coordinate is many orders of magnitude
111
+ // smaller, so the merge math is identical.
112
+ //
113
+ // Note that the storage sentinels in \`meshlet.bounds_box\` and
114
+ // \`geometry.bounding_box\` ARE true ±inf the scatter pass
115
+ // writes the u32 bit pattern directly via \`atomicStore\`, no
116
+ // const-fold involved, and \`aabb_atomic_min_f32\` bitcasts
117
+ // back to f32 at runtime where ±inf is a valid value.
118
+ var thread_min = vec3<f32>( 3.4028234e38);
119
+ var thread_max = vec3<f32>(-3.4028234e38);
120
+
121
+ // Stride loop over the meshlet's vertex slots. Most meshlets fit
122
+ // in a single WG_SIZE pass; larger ones cycle.
123
+ var v: u32 = local_id;
124
+ loop {
125
+ if v >= vertex_count { break; }
126
+ let pos_addr = attribute_section + v * 3u;
127
+ let p = vec3<f32>(
128
+ bitcast<f32>(meshlet_data[pos_addr]),
129
+ bitcast<f32>(meshlet_data[pos_addr + 1u]),
130
+ bitcast<f32>(meshlet_data[pos_addr + 2u]),
131
+ );
132
+ thread_min = min(thread_min, p);
133
+ thread_max = max(thread_max, p);
134
+ v = v + ${WORKGROUP_SIZE}u;
135
+ }
136
+
137
+ // Power-of-2 tree reduction in workgroup memory. WG_SIZE = 64 is
138
+ // a power of two, so the standard halving stride works with no
139
+ // tail handling. Subgroup ops would be a bit faster but require
140
+ // the "subgroups" extension; this works on every device.
141
+ wg_min[local_id] = thread_min;
142
+ wg_max[local_id] = thread_max;
143
+ workgroupBarrier();
144
+
145
+ var stride: u32 = ${WORKGROUP_SIZE >>> 1}u;
146
+ loop {
147
+ if stride == 0u { break; }
148
+ if local_id < stride {
149
+ wg_min[local_id] = min(wg_min[local_id], wg_min[local_id + stride]);
150
+ wg_max[local_id] = max(wg_max[local_id], wg_max[local_id + stride]);
151
+ }
152
+ workgroupBarrier();
153
+ stride = stride >> 1u;
154
+ }
155
+
156
+ // Thread 0 owns the writes. Atomic-merge into both the meshlet's
157
+ // own bounds_box (single contributor per meshlet — could be
158
+ // atomicStore, but using min/max keeps the scatter's sentinel as
159
+ // the identity element and means a re-run is idempotent) AND into
160
+ // the binding's clone geometry's bounding_box (cross-workgroup
161
+ // contention CAS-spin handles it).
162
+ if local_id == 0u {
163
+ let final_min = wg_min[0];
164
+ let final_max = wg_max[0];
165
+
166
+ let m_bounds_base = m_base_words + MESHLET_BOUNDS_OFFSET;
167
+ aabb_atomic_min_f32(&meshlet_metadata_atomic[m_bounds_base + 0u], final_min.x);
168
+ aabb_atomic_min_f32(&meshlet_metadata_atomic[m_bounds_base + 1u], final_min.y);
169
+ aabb_atomic_min_f32(&meshlet_metadata_atomic[m_bounds_base + 2u], final_min.z);
170
+ aabb_atomic_max_f32(&meshlet_metadata_atomic[m_bounds_base + 3u], final_max.x);
171
+ aabb_atomic_max_f32(&meshlet_metadata_atomic[m_bounds_base + 4u], final_max.y);
172
+ aabb_atomic_max_f32(&meshlet_metadata_atomic[m_bounds_base + 5u], final_max.z);
173
+
174
+ let g_base = binding.clone_geometry_index * GEOMETRY_STRIDE + GEOMETRY_BBOX_OFFSET;
175
+ aabb_atomic_min_f32(&geometry_metadata_atomic[g_base + 0u], final_min.x);
176
+ aabb_atomic_min_f32(&geometry_metadata_atomic[g_base + 1u], final_min.y);
177
+ aabb_atomic_min_f32(&geometry_metadata_atomic[g_base + 2u], final_min.z);
178
+ aabb_atomic_max_f32(&geometry_metadata_atomic[g_base + 3u], final_max.x);
179
+ aabb_atomic_max_f32(&geometry_metadata_atomic[g_base + 4u], final_max.y);
180
+ aabb_atomic_max_f32(&geometry_metadata_atomic[g_base + 5u], final_max.z);
181
+ }
182
+ }
183
+ `, [chunk_aabb_atomic_f32]);
184
+
185
+ /**
186
+ * Compute shader that reduces a clone meshlet's deformed vertex
187
+ * positions to a tight AABB, atomic-writes the result to the meshlet's
188
+ * `bounds_box`, and atomic-merges the same bounds into the owning
189
+ * clone geometry's `bounding_box`.
190
+ *
191
+ * Workgroup-per-pair dispatch: one workgroup per (binding, meshlet)
192
+ * row in `dispatch_lookup`. Each thread handles a stride of vertices,
193
+ * the workgroup reduces via shared memory + tree halving, and thread 0
194
+ * commits the result.
195
+ *
196
+ * The geometry-level merge is what lets the rasterizer's per-geometry
197
+ * sphere/AABB culling use post-deformation bounds without a second
198
+ * full pass the sphere derive shader downstream just reads the
199
+ * accumulated `bounding_box` and computes its surrounding sphere.
200
+ *
201
+ * Must run AFTER `shader_meshlet_apply_skinning` (which writes the
202
+ * deformed positions this pass reads) and AFTER
203
+ * `shader_meshlet_bounds_scatter` (which seeds the meshlet and
204
+ * geometry bounds with ±inf sentinels).
205
+ *
206
+ * Pagination: with one workgroup per pair, the host splits into
207
+ * multiple sub-dispatches when `total_pair_count >
208
+ * maxComputeWorkgroupsPerDimension`. The `dispatch_offset` uniform
209
+ * advances per sub-dispatch.
210
+ */
211
+ export const shader_meshlet_bounds_reduce = ComputeShader.from({
212
+ label: "Skinning/MeshletBoundsReduce",
213
+ resources,
214
+ body,
215
+ });
@@ -7,7 +7,7 @@ export const WORKGROUP_SIZE: 64;
7
7
  * Linear-thread dispatch: one thread per (binding, meshlet) pair in
8
8
  * the skinning context's `dispatch_lookup`. With workgroup size 64,
9
9
  * `ceil(total_pair_count / 64)` workgroups cover everything; the
10
- * `dispatch_offset` uniform lets the host paginate when
10
+ * `settings.dispatch_offset` immediate lets the host paginate when
11
11
  * `total_pair_count > maxComputeWorkgroupsPerDimension * 64`
12
12
  * (currently won't trigger — 65535 * 64 ≈ 4M pairs).
13
13
  *
@@ -1 +1 @@
1
- {"version":3,"file":"shader_meshlet_bounds_scatter.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.js"],"names":[],"mappings":"AASA,gCAAiC;AAwFjC;;;;;;;;;;;;;;;;;GAiBG;AACH,0DAIG;8BAlH2B,kCAAkC"}
1
+ {"version":3,"file":"shader_meshlet_bounds_scatter.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.js"],"names":[],"mappings":"AAUA,gCAAiC;AAsGjC;;;;;;;;;;;;;;;;;GAiBG;AACH,0DAIG;8BAhI2B,kCAAkC"}