@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,140 +1,143 @@
1
- import { atomic_u32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
- import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
- import { BVH_NULL_NODE_DEFINITION } from "../../shader/chunk/bvh/BVH_NULL_NODE_DEFINITION.js";
4
- import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
- import { ComputeShader } from "../../shader/ComputeShader.js";
6
- import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
- import {
8
- BVH_NODE_BOUNDS_WORD,
9
- BVH_NODE_CHILD_1_WORD,
10
- BVH_NODE_CHILD_2_WORD,
11
- BVH_NODE_STRIDE_WORDS
12
- } from "./BVH_BUFFER_LAYOUT.js";
13
- import { BVH_BUILD_SETTINGS_STRUCT } from "./BVH_BUILD_SETTINGS_STRUCT.js";
14
-
15
- export const BVH_REFIT_WORKGROUP_SIZE = 64;
16
-
17
- const resources = new ShaderResourceSetDescriptor();
18
- resources.createGroup()
19
- .addUniform("settings", BVH_BUILD_SETTINGS_STRUCT)
20
- .addStorageBuffer("parents", WebGPUArray.from(u32), false)
21
- // node index of each leaf ordinal; the only thing this pass knows about the tree's layout
22
- .addStorageBuffer("leaf_nodes", WebGPUArray.from(u32), false)
23
- // one arrival counter per internal node; must be zero at the start of every build
24
- .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true)
25
- // The same buffer the emission pass wrote as typed nodes, bound flat and atomic here. Every
26
- // word this pass touches is communicated between workgroups, so every access to it is an
27
- // atomic one — the strictest formulation WGSL offers, and the discipline the plan's R1 rests on.
28
- .addStorageBuffer("nodes", WebGPUArray.from(atomic_u32), true);
29
-
30
- const body = CodeChunk.from(
31
- //language=WGSL
32
- `
33
- const NODE_STRIDE = ${BVH_NODE_STRIDE_WORDS}u;
34
- const NODE_BOUNDS = ${BVH_NODE_BOUNDS_WORD}u;
35
- const NODE_CHILD_1 = ${BVH_NODE_CHILD_1_WORD}u;
36
- const NODE_CHILD_2 = ${BVH_NODE_CHILD_2_WORD}u;
37
-
38
- fn bvh_node_word(node: u32) -> u32 {
39
- return settings.node_word_offset + node * NODE_STRIDE;
40
- }
41
-
42
- fn bvh_parent(node: u32) -> u32 {
43
- return parents[settings.parents_offset + node];
44
- }
45
-
46
- fn bvh_read_bounds_low(node_word: u32) -> vec3<f32> {
47
- return vec3<f32>(
48
- bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS])),
49
- bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 1u])),
50
- bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 2u])),
51
- );
52
- }
53
-
54
- fn bvh_read_bounds_high(node_word: u32) -> vec3<f32> {
55
- return vec3<f32>(
56
- bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 3u])),
57
- bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 4u])),
58
- bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 5u])),
59
- );
60
- }
61
-
62
- @compute @workgroup_size(${BVH_REFIT_WORKGROUP_SIZE}, 1, 1)
63
- fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
64
- let i = gid.x;
65
- let n = settings.element_count;
66
-
67
- if (i >= n) {
68
- return;
69
- }
70
-
71
- // Start above leaf i and climb. Which node that leaf is comes from the tree rather than from a
72
- // layout this kernel assumes, so a tree that was built and a tree that was copied refit alike.
73
- var node = bvh_parent(leaf_nodes[settings.leaf_nodes_offset + i]);
74
-
75
- loop {
76
- if (node == BVH_NULL_NODE) {
77
- // climbed past the root
78
- break;
79
- }
80
-
81
- // An internal node has exactly two children, so exactly two climbs pass through it. The
82
- // first arrival exits — its sibling's subtree is still being fitted, and it has nothing to
83
- // wait ON: no spin, no assumption about anyone else's forward progress. The second arrival
84
- // finds both children written and owns the node from here up.
85
- let arrivals = atomicAdd(&counters[node], 1u);
86
-
87
- if (arrivals == 0u) {
88
- break;
89
- }
90
-
91
- let node_word = bvh_node_word(node);
92
-
93
- let child_1 = atomicLoad(&nodes[node_word + NODE_CHILD_1]);
94
- let child_2 = atomicLoad(&nodes[node_word + NODE_CHILD_2]);
95
-
96
- let word_1 = bvh_node_word(child_1);
97
- let word_2 = bvh_node_word(child_2);
98
-
99
- let low = min(bvh_read_bounds_low(word_1), bvh_read_bounds_low(word_2));
100
- let high = max(bvh_read_bounds_high(word_1), bvh_read_bounds_high(word_2));
101
-
102
- atomicStore(&nodes[node_word + NODE_BOUNDS], bitcast<u32>(low.x));
103
- atomicStore(&nodes[node_word + NODE_BOUNDS + 1u], bitcast<u32>(low.y));
104
- atomicStore(&nodes[node_word + NODE_BOUNDS + 2u], bitcast<u32>(low.z));
105
- atomicStore(&nodes[node_word + NODE_BOUNDS + 3u], bitcast<u32>(high.x));
106
- atomicStore(&nodes[node_word + NODE_BOUNDS + 4u], bitcast<u32>(high.y));
107
- atomicStore(&nodes[node_word + NODE_BOUNDS + 5u], bitcast<u32>(high.z));
108
-
109
- node = bvh_parent(node);
110
- }
111
- }
112
- `, [
113
- BVH_NULL_NODE_DEFINITION,
114
- ]);
115
-
116
- /**
117
- * Bottom-up AABB refit — pass 4 of {@link graph_bvh_build_lbvh}, and the last thing a build does.
118
- *
119
- * One thread per leaf climbs the `parents` chain from the node `leaf_nodes` says that leaf occupies,
120
- * taking an arrival counter at each internal node on the way. Nothing waits: the thread that arrives first at a node simply
121
- * dies, and the one that arrives second is guaranteed both children are complete, because the only
122
- * way to arrive is to have finished a child. That is the whole synchronisation, and it assumes
123
- * atomic-word visibility rather than any scheduling fairness which is why it sits on the accepted
124
- * side of the engine's line on cross-workgroup communication.
125
- *
126
- * The counters must be zero when the pass starts; the graph declares them with a clear range so a
127
- * pool-reused buffer is cleared and a fresh one arrives zeroed already.
128
- *
129
- * The same pass serves refit-only updates (topology frozen, leaf bounds rewritten) which is what
130
- * per-frame skinned BLAS needs so it exists as a standalone dispatch rather than fused into
131
- * emission. Node indices are local to the tree and `settings.node_word_offset` says where node 0
132
- * lands, so a BLAS living inside the shared geometry arena refits through this same kernel.
133
- *
134
- * @type {ComputeShader}
135
- */
136
- export const shader_bvh_refit = ComputeShader.from({
137
- label: "BVHBuild/Refit",
138
- resources,
139
- body,
140
- });
1
+ import { atomic_u32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
+ import { BVH_NULL_NODE_DEFINITION } from "../../shader/chunk/bvh/BVH_NULL_NODE_DEFINITION.js";
4
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
+ import { ComputeShader } from "../../shader/ComputeShader.js";
6
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
+ import {
8
+ BVH_NODE_BOUNDS_WORD,
9
+ BVH_NODE_CHILD_1_WORD,
10
+ BVH_NODE_CHILD_2_WORD,
11
+ BVH_NODE_STRIDE_WORDS
12
+ } from "./BVH_BUFFER_LAYOUT.js";
13
+ import { BVH_BUILD_SETTINGS_STRUCT } from "./BVH_BUILD_SETTINGS_STRUCT.js";
14
+
15
+ export const BVH_REFIT_WORKGROUP_SIZE = 64;
16
+
17
+ const resources = new ShaderResourceSetDescriptor();
18
+
19
+ // see shader_bvh_morton — the same build settings, carried as immediate data
20
+ resources.setImmediate("settings", BVH_BUILD_SETTINGS_STRUCT);
21
+
22
+ resources.createGroup()
23
+ .addStorageBuffer("parents", WebGPUArray.from(u32), false)
24
+ // node index of each leaf ordinal; the only thing this pass knows about the tree's layout
25
+ .addStorageBuffer("leaf_nodes", WebGPUArray.from(u32), false)
26
+ // one arrival counter per internal node; must be zero at the start of every build
27
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true)
28
+ // The same buffer the emission pass wrote as typed nodes, bound flat and atomic here. Every
29
+ // word this pass touches is communicated between workgroups, so every access to it is an
30
+ // atomic one — the strictest formulation WGSL offers, and the discipline the plan's R1 rests on.
31
+ .addStorageBuffer("nodes", WebGPUArray.from(atomic_u32), true);
32
+
33
+ const body = CodeChunk.from(
34
+ //language=WGSL
35
+ `
36
+ const NODE_STRIDE = ${BVH_NODE_STRIDE_WORDS}u;
37
+ const NODE_BOUNDS = ${BVH_NODE_BOUNDS_WORD}u;
38
+ const NODE_CHILD_1 = ${BVH_NODE_CHILD_1_WORD}u;
39
+ const NODE_CHILD_2 = ${BVH_NODE_CHILD_2_WORD}u;
40
+
41
+ fn bvh_node_word(node: u32) -> u32 {
42
+ return settings.node_word_offset + node * NODE_STRIDE;
43
+ }
44
+
45
+ fn bvh_parent(node: u32) -> u32 {
46
+ return parents[settings.parents_offset + node];
47
+ }
48
+
49
+ fn bvh_read_bounds_low(node_word: u32) -> vec3<f32> {
50
+ return vec3<f32>(
51
+ bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS])),
52
+ bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 1u])),
53
+ bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 2u])),
54
+ );
55
+ }
56
+
57
+ fn bvh_read_bounds_high(node_word: u32) -> vec3<f32> {
58
+ return vec3<f32>(
59
+ bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 3u])),
60
+ bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 4u])),
61
+ bitcast<f32>(atomicLoad(&nodes[node_word + NODE_BOUNDS + 5u])),
62
+ );
63
+ }
64
+
65
+ @compute @workgroup_size(${BVH_REFIT_WORKGROUP_SIZE}, 1, 1)
66
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
67
+ let i = gid.x;
68
+ let n = settings.element_count;
69
+
70
+ if (i >= n) {
71
+ return;
72
+ }
73
+
74
+ // Start above leaf i and climb. Which node that leaf is comes from the tree rather than from a
75
+ // layout this kernel assumes, so a tree that was built and a tree that was copied refit alike.
76
+ var node = bvh_parent(leaf_nodes[settings.leaf_nodes_offset + i]);
77
+
78
+ loop {
79
+ if (node == BVH_NULL_NODE) {
80
+ // climbed past the root
81
+ break;
82
+ }
83
+
84
+ // An internal node has exactly two children, so exactly two climbs pass through it. The
85
+ // first arrival exits — its sibling's subtree is still being fitted, and it has nothing to
86
+ // wait ON: no spin, no assumption about anyone else's forward progress. The second arrival
87
+ // finds both children written and owns the node from here up.
88
+ let arrivals = atomicAdd(&counters[node], 1u);
89
+
90
+ if (arrivals == 0u) {
91
+ break;
92
+ }
93
+
94
+ let node_word = bvh_node_word(node);
95
+
96
+ let child_1 = atomicLoad(&nodes[node_word + NODE_CHILD_1]);
97
+ let child_2 = atomicLoad(&nodes[node_word + NODE_CHILD_2]);
98
+
99
+ let word_1 = bvh_node_word(child_1);
100
+ let word_2 = bvh_node_word(child_2);
101
+
102
+ let low = min(bvh_read_bounds_low(word_1), bvh_read_bounds_low(word_2));
103
+ let high = max(bvh_read_bounds_high(word_1), bvh_read_bounds_high(word_2));
104
+
105
+ atomicStore(&nodes[node_word + NODE_BOUNDS], bitcast<u32>(low.x));
106
+ atomicStore(&nodes[node_word + NODE_BOUNDS + 1u], bitcast<u32>(low.y));
107
+ atomicStore(&nodes[node_word + NODE_BOUNDS + 2u], bitcast<u32>(low.z));
108
+ atomicStore(&nodes[node_word + NODE_BOUNDS + 3u], bitcast<u32>(high.x));
109
+ atomicStore(&nodes[node_word + NODE_BOUNDS + 4u], bitcast<u32>(high.y));
110
+ atomicStore(&nodes[node_word + NODE_BOUNDS + 5u], bitcast<u32>(high.z));
111
+
112
+ node = bvh_parent(node);
113
+ }
114
+ }
115
+ `, [
116
+ BVH_NULL_NODE_DEFINITION,
117
+ ]);
118
+
119
+ /**
120
+ * Bottom-up AABB refit pass 4 of {@link graph_bvh_build_lbvh}, and the last thing a build does.
121
+ *
122
+ * One thread per leaf climbs the `parents` chain from the node `leaf_nodes` says that leaf occupies,
123
+ * taking an arrival counter at each internal node on the way. Nothing waits: the thread that arrives first at a node simply
124
+ * dies, and the one that arrives second is guaranteed both children are complete, because the only
125
+ * way to arrive is to have finished a child. That is the whole synchronisation, and it assumes
126
+ * atomic-word visibility rather than any scheduling fairness which is why it sits on the accepted
127
+ * side of the engine's line on cross-workgroup communication.
128
+ *
129
+ * The counters must be zero when the pass starts; the graph declares them with a clear range so a
130
+ * pool-reused buffer is cleared and a fresh one arrives zeroed already.
131
+ *
132
+ * The same pass serves refit-only updates (topology frozen, leaf bounds rewritten) which is what
133
+ * per-frame skinned BLAS needs — so it exists as a standalone dispatch rather than fused into
134
+ * emission. Node indices are local to the tree and `settings.node_word_offset` says where node 0
135
+ * lands, so a BLAS living inside the shared geometry arena refits through this same kernel.
136
+ *
137
+ * @type {ComputeShader}
138
+ */
139
+ export const shader_bvh_refit = ComputeShader.from({
140
+ label: "BVHBuild/Refit",
141
+ resources,
142
+ body,
143
+ });
@@ -18,8 +18,8 @@
18
18
  * And it reports what the risk register asks to be measured rather than assumed: the depth
19
19
  * histogram against the shared traversal stack, and the SAH cost of the tree.
20
20
  *
21
- * Per-pass GPU timings go to the console for the largest case, through the debug-timers path —
22
- * the `timer` argument `graph_compute_pass` forwards is silently dropped by
21
+ * Per-pass GPU timings go to the console for the largest case, through a {@link GPUFrameRecorder}
22
+ * of its own — the `timer` argument `graph_compute_pass` forwards is silently dropped by
23
23
  * `ComputeShader.dispatch`, so this is the path that actually reports anything.
24
24
  *
25
25
  * One graph and one submission per case: the transients then come and go with each build instead
@@ -1 +1 @@
1
- {"version":3,"file":"verify_gpu_bvh_build.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.js"],"names":[],"mappings":"AAwQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,sEAKC"}
1
+ {"version":3,"file":"verify_gpu_bvh_build.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.js"],"names":[],"mappings":"AAyQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,sEAKC"}
@@ -2,6 +2,7 @@ import { BVH } from "../../../../core/bvh2/bvh3/BVH.js";
2
2
  import { ebvh_build_hierarchy_radix } from "../../../../core/bvh2/bvh3/ebvh_build_hierarchy_radix.js";
3
3
  import { FrameGraph } from "../../../../engine/graphics/render/frame_graph/FrameGraph.js";
4
4
  import { ShadeGPUCommandContext } from "../../../device/ShadeGPUCommandContext.js";
5
+ import { GPUFrameRecorder } from "../../../device/timing/profile/GPUFrameRecorder.js";
5
6
  import { f32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
6
7
  import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
7
8
  import { graph_inspect_gpu_buffer } from "../../buffer/graph_inspect_gpu_buffer.js";
@@ -282,8 +283,8 @@ function check(test_case, input, tree, sorted_keys, sorted_values) {
282
283
  * And it reports what the risk register asks to be measured rather than assumed: the depth
283
284
  * histogram against the shared traversal stack, and the SAH cost of the tree.
284
285
  *
285
- * Per-pass GPU timings go to the console for the largest case, through the debug-timers path —
286
- * the `timer` argument `graph_compute_pass` forwards is silently dropped by
286
+ * Per-pass GPU timings go to the console for the largest case, through a {@link GPUFrameRecorder}
287
+ * of its own — the `timer` argument `graph_compute_pass` forwards is silently dropped by
287
288
  * `ComputeShader.dispatch`, so this is the path that actually reports anything.
288
289
  *
289
290
  * One graph and one submission per case: the transients then come and go with each build instead
@@ -310,13 +311,22 @@ function run_case(graphics, test_case) {
310
311
 
311
312
  const cmd = ShadeGPUCommandContext.create(graphics, `verify/gpu bvh build/${test_case.name}`);
312
313
 
313
- // Only the large case: the number worth having is the build time at scale, and a table per
314
- // case would bury it.
314
+ /**
315
+ * Only the large case: the number worth having is the build time at scale, and a table per case
316
+ * would bury it.
317
+ *
318
+ * @type {GPUFrameRecorder|null}
319
+ */
320
+ let recorder = null;
321
+
315
322
  if (test_case.count >= 100000) {
316
- cmd.enable_debug_timers(table => {
317
- console.log(`[BVH] GPU timings — ${test_case.name}`);
318
- console.table(table);
319
- });
323
+ recorder = new GPUFrameRecorder(0, performance.now());
324
+
325
+ // dispatch and invocation counts alongside the durations — for a build, the interesting
326
+ // question is which pass is the wrong shape, not only which is slow
327
+ recorder.enable_work_capture();
328
+
329
+ cmd.enable_profiling(recorder, 0);
320
330
  }
321
331
 
322
332
  const storage_usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC;
@@ -417,6 +427,31 @@ function run_case(graphics, test_case) {
417
427
  });
418
428
  }
419
429
 
430
+ if (recorder !== null) {
431
+ // subscribed before the graph runs, so each pass is attributed to the node that opened it
432
+ recorder.attach_graph(graph);
433
+ }
434
+
420
435
  cmd.encodeGraph(graph);
421
436
  cmd.finish();
437
+
438
+ if (recorder !== null) {
439
+ const captured = recorder;
440
+
441
+ /*
442
+ `profiling_absorbed`, not `done`. `done` resolves at submit, before a single timestamp has
443
+ been read back — closing there reports an empty table every time.
444
+ */
445
+ cmd.profiling_absorbed.then(() => {
446
+ const frame = captured.close(performance.now());
447
+
448
+ console.log(`[BVH] GPU timings — ${test_case.name}`);
449
+ console.table(frame.spans.map(span => ({
450
+ label: span.label,
451
+ duration_ms: span.duration_ns * 1e-6,
452
+ dispatches: span.work?.dispatch_count ?? 0,
453
+ invocations: span.work?.invocation_count ?? 0
454
+ })));
455
+ });
456
+ }
422
457
  }
@@ -1 +1 @@
1
- {"version":3,"file":"graph_radix_sort.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,uFAFa;IAAC,IAAI,EAAC,MAAM,CAAC;IAAC,MAAM,EAAC,MAAM,CAAA;CAAC,CA4JxC"}
1
+ {"version":3,"file":"graph_radix_sort.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,uFAFa;IAAC,IAAI,EAAC,MAAM,CAAC;IAAC,MAAM,EAAC,MAAM,CAAA;CAAC,CA4JxC"}
@@ -4,7 +4,6 @@ import { warn_limited } from "../../../util/warn_limited.js";
4
4
  import { BufferResourceDescriptor } from "../../../device/graph/BufferResourceDescriptor.js";
5
5
  import { graph_prefix_scan_csdldf } from "../prefix_sum/v1/graph_prefix_scan_csdldf.js";
6
6
  import { RADIX, RADIX_LOG, RADIX_PASSES, SORT_TILE_SIZE, SPINE_HEADER_WORDS } from "./defs.js";
7
- import { SORT_PASS_SETTINGS_STRUCT } from "./SORT_PASS_SETTINGS_STRUCT.js";
8
7
  import { shader_radix_sort_histogram } from "./shader_radix_sort_histogram.js";
9
8
  import { shader_radix_sort_scatter } from "./shader_radix_sort_scatter.js";
10
9
 
@@ -95,11 +94,11 @@ export function graph_radix_sort({
95
94
  encoder,
96
95
  group_count_x: tile_count,
97
96
  bindings: {
98
- settings: encoder.allocateTransientValueBuffer(SORT_PASS_SETTINGS_STRUCT, {
97
+ settings: {
99
98
  shift: pass_data.shift,
100
99
  element_count,
101
100
  tile_count,
102
- }),
101
+ },
103
102
  keys: resources.get(pass_data.keys),
104
103
  spine: resources.get(pass_data.spine),
105
104
  }
@@ -130,11 +129,11 @@ export function graph_radix_sort({
130
129
  encoder,
131
130
  group_count_x: tile_count,
132
131
  bindings: {
133
- settings: encoder.allocateTransientValueBuffer(SORT_PASS_SETTINGS_STRUCT, {
132
+ settings: {
134
133
  shift: pass_data.shift,
135
134
  element_count,
136
135
  tile_count,
137
- }),
136
+ },
138
137
  in_keys,
139
138
  in_values,
140
139
  out_keys,
@@ -1 +1 @@
1
- {"version":3,"file":"shader_radix_sort_histogram.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js"],"names":[],"mappings":"AAkEA;;;;;;;;;;;;GAYG;AACH,0CAFU,aAAa,CAMpB;8BAhF2B,+BAA+B"}
1
+ {"version":3,"file":"shader_radix_sort_histogram.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js"],"names":[],"mappings":"AAsEA;;;;;;;;;;;;GAYG;AACH,0CAFU,aAAa,CAMpB;8BApF2B,+BAA+B"}
@@ -1,84 +1,88 @@
1
- import { u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
- import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
- import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
4
- import { ComputeShader } from "../../shader/ComputeShader.js";
5
- import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
6
- import { chunk_sort_digit } from "./chunk_sort_digit.js";
7
- import { RADIX, SORT_KEYS_PER_THREAD, SORT_TILE_SIZE, SORT_WORKGROUP_SIZE } from "./defs.js";
8
- import { SORT_PASS_SETTINGS_STRUCT } from "./SORT_PASS_SETTINGS_STRUCT.js";
9
-
10
- const resources = new ShaderResourceSetDescriptor();
11
- resources.createGroup()
12
- .addUniform("settings", SORT_PASS_SETTINGS_STRUCT)
13
- .addStorageBuffer("keys", WebGPUArray.from(u32), false)
14
- // `{count: u32, elements: array<vec4u>}` as the scan sees it, flat as this pass writes it.
15
- // Every cell is produced by exactly one thread of one workgroup, so no atomics: the only
16
- // consumer is a later dispatch, and WebGPU orders dispatches against each other.
17
- .addStorageBuffer("spine", WebGPUArray.from(u32), true);
18
-
19
- const body = CodeChunk.from(
20
- //language=WGSL
21
- `
22
- const WORKGROUP_SIZE = ${SORT_WORKGROUP_SIZE}u;
23
- const KEYS_PER_THREAD = ${SORT_KEYS_PER_THREAD}u;
24
- const TILE_SIZE = ${SORT_TILE_SIZE}u;
25
- const RADIX = ${RADIX}u;
26
-
27
- // One bin per thread — RADIX and the workgroup size are equal, so the clear and the write-out are
28
- // both a single unstrided step.
29
- var<workgroup> wg_histogram: array<atomic<u32>, RADIX>;
30
-
31
- @compute @workgroup_size(WORKGROUP_SIZE, 1, 1)
32
- fn main(
33
- @builtin(local_invocation_index) thread_id: u32,
34
- @builtin(workgroup_id) workgroup_id: vec3<u32>,
35
- ) {
36
- let tile = workgroup_id.x;
37
-
38
- atomicStore(&wg_histogram[thread_id], 0u);
39
-
40
- workgroupBarrier();
41
-
42
- // Striped so that neighbouring threads read neighbouring addresses. The tail tile is partial;
43
- // the keys past the end are not counted, which is what lets the scatter recognise them later
44
- // by position alone.
45
- let tile_base = tile * TILE_SIZE;
46
- for (var k = 0u; k < KEYS_PER_THREAD; k += 1u) {
47
- let source = tile_base + k * WORKGROUP_SIZE + thread_id;
48
-
49
- if (source < settings.element_count) {
50
- atomicAdd(&wg_histogram[sort_extract_digit(keys[source], settings.shift)], 1u);
51
- }
52
- }
53
-
54
- workgroupBarrier();
55
-
56
- spine[sort_spine_index(thread_id, tile, settings.tile_count)] = atomicLoad(&wg_histogram[thread_id]);
57
-
58
- // The scan is indirect-dispatched off an element count it reads from word 0 of this buffer.
59
- if (tile == 0u && thread_id == 0u) {
60
- spine[0] = settings.tile_count * RADIX;
61
- }
62
- }
63
- `, [
64
- chunk_sort_digit,
65
- ]);
66
-
67
- /**
68
- * Per-tile 256-bin digit histogram — stage (a) of one digit pass of {@link graph_radix_sort}.
69
- *
70
- * One workgroup per tile; the counts land in the spine bin-major, so that the single scan that
71
- * follows produces global digit offsets and per-tile offsets in one traversal.
72
- *
73
- * Subgroup ballot peer-aggregation ahead of the workgroup atomics (the deleted one-sweep port's
74
- * `WarpLevelMultiSplit`) is the recorded upgrade here; it is left out of v1 because this pass reads
75
- * each key once and is bandwidth-shaped, while the machinery it needs is the widest part of the
76
- * subgroup-size surface.
77
- *
78
- * @type {ComputeShader}
79
- */
80
- export const shader_radix_sort_histogram = ComputeShader.from({
81
- label: "RadixSort/Histogram",
82
- resources,
83
- body,
84
- });
1
+ import { u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
4
+ import { ComputeShader } from "../../shader/ComputeShader.js";
5
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
6
+ import { chunk_sort_digit } from "./chunk_sort_digit.js";
7
+ import { RADIX, SORT_KEYS_PER_THREAD, SORT_TILE_SIZE, SORT_WORKGROUP_SIZE } from "./defs.js";
8
+ import { SORT_PASS_SETTINGS_STRUCT } from "./SORT_PASS_SETTINGS_STRUCT.js";
9
+
10
+ const resources = new ShaderResourceSetDescriptor();
11
+
12
+ // per-pass, 12 bytes, read-only: immediate data rather than a uniform buffer. A 32-bit key sort
13
+ // runs four passes, and both this shader and the scatter took a buffer of their own in each.
14
+ resources.setImmediate("settings", SORT_PASS_SETTINGS_STRUCT);
15
+
16
+ resources.createGroup()
17
+ .addStorageBuffer("keys", WebGPUArray.from(u32), false)
18
+ // `{count: u32, elements: array<vec4u>}` as the scan sees it, flat as this pass writes it.
19
+ // Every cell is produced by exactly one thread of one workgroup, so no atomics: the only
20
+ // consumer is a later dispatch, and WebGPU orders dispatches against each other.
21
+ .addStorageBuffer("spine", WebGPUArray.from(u32), true);
22
+
23
+ const body = CodeChunk.from(
24
+ //language=WGSL
25
+ `
26
+ const WORKGROUP_SIZE = ${SORT_WORKGROUP_SIZE}u;
27
+ const KEYS_PER_THREAD = ${SORT_KEYS_PER_THREAD}u;
28
+ const TILE_SIZE = ${SORT_TILE_SIZE}u;
29
+ const RADIX = ${RADIX}u;
30
+
31
+ // One bin per thread — RADIX and the workgroup size are equal, so the clear and the write-out are
32
+ // both a single unstrided step.
33
+ var<workgroup> wg_histogram: array<atomic<u32>, RADIX>;
34
+
35
+ @compute @workgroup_size(WORKGROUP_SIZE, 1, 1)
36
+ fn main(
37
+ @builtin(local_invocation_index) thread_id: u32,
38
+ @builtin(workgroup_id) workgroup_id: vec3<u32>,
39
+ ) {
40
+ let tile = workgroup_id.x;
41
+
42
+ atomicStore(&wg_histogram[thread_id], 0u);
43
+
44
+ workgroupBarrier();
45
+
46
+ // Striped so that neighbouring threads read neighbouring addresses. The tail tile is partial;
47
+ // the keys past the end are not counted, which is what lets the scatter recognise them later
48
+ // by position alone.
49
+ let tile_base = tile * TILE_SIZE;
50
+ for (var k = 0u; k < KEYS_PER_THREAD; k += 1u) {
51
+ let source = tile_base + k * WORKGROUP_SIZE + thread_id;
52
+
53
+ if (source < settings.element_count) {
54
+ atomicAdd(&wg_histogram[sort_extract_digit(keys[source], settings.shift)], 1u);
55
+ }
56
+ }
57
+
58
+ workgroupBarrier();
59
+
60
+ spine[sort_spine_index(thread_id, tile, settings.tile_count)] = atomicLoad(&wg_histogram[thread_id]);
61
+
62
+ // The scan is indirect-dispatched off an element count it reads from word 0 of this buffer.
63
+ if (tile == 0u && thread_id == 0u) {
64
+ spine[0] = settings.tile_count * RADIX;
65
+ }
66
+ }
67
+ `, [
68
+ chunk_sort_digit,
69
+ ]);
70
+
71
+ /**
72
+ * Per-tile 256-bin digit histogram — stage (a) of one digit pass of {@link graph_radix_sort}.
73
+ *
74
+ * One workgroup per tile; the counts land in the spine bin-major, so that the single scan that
75
+ * follows produces global digit offsets and per-tile offsets in one traversal.
76
+ *
77
+ * Subgroup ballot peer-aggregation ahead of the workgroup atomics (the deleted one-sweep port's
78
+ * `WarpLevelMultiSplit`) is the recorded upgrade here; it is left out of v1 because this pass reads
79
+ * each key once and is bandwidth-shaped, while the machinery it needs is the widest part of the
80
+ * subgroup-size surface.
81
+ *
82
+ * @type {ComputeShader}
83
+ */
84
+ export const shader_radix_sort_histogram = ComputeShader.from({
85
+ label: "RadixSort/Histogram",
86
+ resources,
87
+ body,
88
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"shader_radix_sort_scatter.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js"],"names":[],"mappings":"AA8KA;;;;;;;;;;;GAWG;AACH,wCAFU,aAAa,CAMpB;8BA1L2B,+BAA+B"}
1
+ {"version":3,"file":"shader_radix_sort_scatter.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js"],"names":[],"mappings":"AAiLA;;;;;;;;;;;GAWG;AACH,wCAFU,aAAa,CAMpB;8BA7L2B,+BAA+B"}