@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,383 +1,379 @@
1
- import { assert } from "../../../core/assert.js";
2
- import { BVH } from "../../../core/bvh2/bvh3/BVH.js";
3
- import { FrameGraph } from "../../../engine/graphics/render/frame_graph/FrameGraph.js";
4
- import { BufferResourceDescriptor } from "../../device/graph/BufferResourceDescriptor.js";
5
- import { ShadeGPUCommandContext } from "../../device/ShadeGPUCommandContext.js";
6
- import { ensure_buffer_capacity } from "../geometry/make_temp_gpu_buffer.js";
7
- import { BVH_BUILD_SETTINGS_STRUCT } from "../gpu_primitive/bvh/BVH_BUILD_SETTINGS_STRUCT.js";
8
- import { bvh_buffer_size } from "../gpu_primitive/bvh/BVH_BUFFER_LAYOUT.js";
9
- import { graph_bvh_build_lbvh } from "../gpu_primitive/bvh/graph_bvh_build_lbvh.js";
10
- import { shader_bvh_extract_instance_leaves } from "./shader_bvh_extract_instance_leaves.js";
11
-
12
- /**
13
- * `root = BVH_NULL_NODE` — an empty tree, in the four bytes every consumer already reads that way.
14
- * @type {Uint32Array}
15
- */
16
- const EMPTY_TREE = Uint32Array.from([0xffffffff]);
17
-
18
- /**
19
- * The scene-bounds cell before anything has been merged into it: +inf for the three minima, -inf
20
- * for the three maxima, so the first contribution wins on every axis.
21
- *
22
- * Written host-side as exact u32 bit patterns. A pool-cleared buffer holds zeroes, and zero is a
23
- * perfectly good coordinate a scene entirely in the positive octant would end up with bounds
24
- * anchored at the origin and every Morton code crushed into a corner of the grid.
25
- *
26
- * @type {Uint32Array}
27
- */
28
- const SCENE_BOUNDS_SEED = Uint32Array.from([
29
- 0x7F800000, 0x7F800000, 0x7F800000,
30
- 0xFF800000, 0xFF800000, 0xFF800000,
31
- ]);
32
-
33
- /**
34
- * Top-Level Acceleration Structure (TLAS)
35
- */
36
- export class GPUInstancesAccelerationStructure {
37
-
38
- /**
39
- * @type {GraphicsContext}
40
- */
41
- #graphics
42
-
43
- /**
44
- * @type {GPUDevice}
45
- */
46
- #device
47
-
48
- #bvh = new BVH();
49
-
50
- /**
51
- * The CPU-side tree. Still maintained incrementally by the `instance_*` methods and still walked
52
- * by CPU queries {@link DirectionalLightShadowmap} runs `compute_tight_near_far_clipping_planes`
53
- * against it per cascade per frame. What the GPU build retires is the per-frame treelet pass and
54
- * the full flatten-and-upload, not the tree.
55
- */
56
- get bvh() {
57
- return this.#bvh;
58
- }
59
-
60
- clear() {
61
- this.#bvh.release_all();
62
- this.#node_mapping.clear();
63
- this.#membership_version++;
64
- this.#version++;
65
- }
66
-
67
- /**
68
- * @type {GPUBuffer}
69
- */
70
- #buffer
71
-
72
- /**
73
- *
74
- * @return {GPUBuffer}
75
- */
76
- get buffer() {
77
- return this.#buffer;
78
- }
79
-
80
- #gpu_version = 0;
81
- #version = 0;
82
-
83
- /**
84
- * Bumped when the set of live rows changes an add or a remove and not when one merely moves.
85
- * The rows list is uploaded only when this moves, so a scene in continuous motion re-uploads
86
- * nothing.
87
- *
88
- * @type {number}
89
- */
90
- #membership_version = 0;
91
-
92
- /**
93
- * Membership version the {@link #rows_buffer} currently holds.
94
- * @type {number}
95
- */
96
- #rows_gpu_version = -1;
97
-
98
- /**
99
- * Compact mirror of the live `meshes` rows, in insertion order. Rebuilt from
100
- * {@link #node_mapping} when membership churns.
101
- *
102
- * @type {Uint32Array}
103
- */
104
- #rows = new Uint32Array(0);
105
-
106
- /**
107
- * @type {GPUBuffer|undefined}
108
- */
109
- #rows_buffer
110
-
111
- /**
112
- *
113
- * @param {GraphicsContext} graphics
114
- */
115
- constructor(graphics) {
116
- assert.defined(graphics, 'graphics');
117
- assert.equal(graphics.isGraphicsContext, true, 'graphics.isGraphicsContext !== true');
118
-
119
- const device = graphics.device;
120
-
121
- this.#graphics = graphics;
122
- this.#device = device;
123
-
124
- this.#buffer = device.createBuffer({
125
- label: 'TLAS',
126
- size: 1024,
127
- usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
128
- });
129
- }
130
-
131
- /**
132
- *
133
- * @type {Map<number, number>}
134
- */
135
- #node_mapping = new Map();
136
-
137
- /**
138
- *
139
- * @param {number} index
140
- * @param {Mesh} instance
141
- */
142
- instance_add(index, instance) {
143
- assert.isNonNegativeInteger(index, 'index');
144
- assert.defined(instance, 'instance');
145
-
146
- const bvh = this.#bvh;
147
-
148
- const node = bvh.allocate_node();
149
- bvh.node_set_user_data(node, index);
150
- bvh.node_set_aabb(node, instance.bounding_box);
151
-
152
- bvh.insert_leaf(node);
153
-
154
- this.#node_mapping.set(index, node);
155
-
156
- this.#membership_version++;
157
- this.#version++;
158
- }
159
-
160
- /**
161
- * Drop an instance previously handed to {@link instance_add}. The leaf is unlinked and its node
162
- * returned to the pool, so the tree stays proportional to what is in the scene rather than to
163
- * everything that ever was.
164
- *
165
- * @param {number} index
166
- */
167
- instance_remove(index) {
168
- assert.isNonNegativeInteger(index, 'index');
169
-
170
- const node = this.#node_mapping.get(index);
171
-
172
- assert.defined(node, 'node');
173
-
174
- const bvh = this.#bvh;
175
-
176
- bvh.remove_leaf(node);
177
- bvh.release_node(node);
178
-
179
- this.#node_mapping.delete(index);
180
-
181
- this.#membership_version++;
182
- this.#version++;
183
- }
184
-
185
- /**
186
- *
187
- * @param {number} index
188
- * @param {Mesh} instance
189
- */
190
- instance_update(index, instance) {
191
- assert.isNonNegativeInteger(index, 'index');
192
- assert.defined(instance, 'instance');
193
-
194
- const node = this.#node_mapping.get(index);
195
-
196
- this.#bvh.node_move_aabb(node, instance.bounding_box);
197
-
198
- this.#version++;
199
- }
200
-
201
- /**
202
- * Bring {@link #rows_buffer} in line with the live row set, if and only if membership changed.
203
- *
204
- * @returns {number} number of live rows
205
- */
206
- #refresh_rows() {
207
- const count = this.#node_mapping.size;
208
-
209
- if (this.#rows_gpu_version === this.#membership_version && this.#rows.length >= count) {
210
- return count;
211
- }
212
-
213
- if (this.#rows.length < count) {
214
- this.#rows = new Uint32Array(count);
215
- }
216
-
217
- let i = 0;
218
- for (const row of this.#node_mapping.keys()) {
219
- this.#rows[i] = row;
220
- i++;
221
- }
222
-
223
- const byte_size = Math.max(4, count * Uint32Array.BYTES_PER_ELEMENT);
224
-
225
- if (this.#rows_buffer === undefined) {
226
- this.#rows_buffer = this.#device.createBuffer({
227
- label: 'TLAS/rows',
228
- size: Math.max(1024, byte_size),
229
- usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
230
- });
231
- } else {
232
- this.#rows_buffer = ensure_buffer_capacity(this.#device, this.#rows_buffer, byte_size);
233
- }
234
-
235
- // Queue writes land in submission order ahead of command buffers submitted after them, so
236
- // the build encoded below sees these rows. Offset and size are in elements of the source,
237
- // per `GPUQueue.writeBuffer` `#rows` can be longer than the live set.
238
- this.#device.queue.writeBuffer(this.#rows_buffer, 0, this.#rows, 0, count);
239
-
240
- this.#rows_gpu_version = this.#membership_version;
241
-
242
- return count;
243
- }
244
-
245
- /**
246
- * Build the tree, from the world AABBs the scene database holds.
247
- *
248
- * @param {GPUBuffer} scene_database_buffer
249
- */
250
- #build(scene_database_buffer) {
251
- assert.defined(scene_database_buffer, 'scene_database_buffer');
252
-
253
- const device = this.#device;
254
-
255
- const element_count = this.#node_mapping.size;
256
-
257
- // `ensure_buffer_capacity` can hand back a NEW buffer and destroy the old one. Consumers are
258
- // safe because they read `tlas.buffer` per frame at pass-execute time — but the field has to
259
- // be reassigned before the graph imports it.
260
- this.#buffer = ensure_buffer_capacity(
261
- device,
262
- this.#buffer,
263
- bvh_buffer_size(Math.max(1, element_count)),
264
- 1024,
265
- 1024,
266
- 1.2
267
- );
268
-
269
- if (element_count === 0) {
270
- device.queue.writeBuffer(this.#buffer, 0, EMPTY_TREE);
271
-
272
- return;
273
- }
274
-
275
- this.#refresh_rows();
276
-
277
- const graph = new FrameGraph('TLAS build');
278
-
279
- const rows = graph.import_resource(
280
- "tlas/rows",
281
- BufferResourceDescriptor.fromBuffer(this.#rows_buffer),
282
- this.#rows_buffer
283
- );
284
-
285
- const scene_database = graph.import_resource(
286
- "scene database",
287
- BufferResourceDescriptor.fromBuffer(scene_database_buffer),
288
- scene_database_buffer
289
- );
290
-
291
- const nodes = graph.import_resource(
292
- "tlas/nodes",
293
- BufferResourceDescriptor.fromBuffer(this.#buffer),
294
- this.#buffer
295
- );
296
-
297
- const extract_data = {};
298
- const extract_pass = graph.add("tlas/extract instance leaves", extract_data, extract_execute);
299
-
300
- extract_data.element_count = element_count;
301
- extract_data.rows = extract_pass.read(rows);
302
- extract_data.scene_database = extract_pass.read(scene_database);
303
-
304
- extract_data.leaf_bounds = extract_pass.create("tlas/leaf bounds", BufferResourceDescriptor.from(
305
- element_count * 6 * Float32Array.BYTES_PER_ELEMENT,
306
- GPUBufferUsage.STORAGE
307
- ));
308
-
309
- extract_data.leaf_payload = extract_pass.create("tlas/leaf payload", BufferResourceDescriptor.from(
310
- element_count * Uint32Array.BYTES_PER_ELEMENT,
311
- GPUBufferUsage.STORAGE
312
- ));
313
-
314
- extract_data.scene_bounds = extract_pass.create("tlas/scene bounds", BufferResourceDescriptor.from(
315
- SCENE_BOUNDS_SEED.byteLength,
316
- GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
317
- ));
318
-
319
- graph_bvh_build_lbvh({
320
- graph,
321
- leaf_bounds: extract_data.leaf_bounds,
322
- leaf_payload: extract_data.leaf_payload,
323
- scene_bounds: extract_data.scene_bounds,
324
- element_count,
325
- nodes,
326
- });
327
-
328
- const cmd = ShadeGPUCommandContext.create(this.#graphics, 'TLAS/build');
329
-
330
- cmd.encodeGraph(graph);
331
- cmd.finish();
332
- }
333
-
334
- /**
335
- * @param {GPUBuffer} scene_database_buffer the table the world AABBs are read from
336
- */
337
- push_to_gpu(scene_database_buffer) {
338
- this.#build(scene_database_buffer);
339
-
340
- this.#gpu_version = this.#version;
341
- }
342
-
343
- /**
344
- * @param {GPUBuffer} scene_database_buffer
345
- */
346
- update(scene_database_buffer) {
347
- if (this.#gpu_version === this.#version) {
348
- return;
349
- }
350
-
351
- this.push_to_gpu(scene_database_buffer);
352
- }
353
- }
354
-
355
- /**
356
- * @param pass_data
357
- * @param {FramePassResources} resources
358
- * @param {GraphicsExecutionContext} context
359
- */
360
- function extract_execute(pass_data, resources, context) {
361
- const encoder = context.encoder;
362
-
363
- const scene_bounds = resources.get(pass_data.scene_bounds);
364
-
365
- // Seeded rather than cleared: the merge is a min/max, and zero is not an identity for either.
366
- encoder.writeBuffer(scene_bounds, 0, SCENE_BOUNDS_SEED.buffer, 0, SCENE_BOUNDS_SEED.byteLength);
367
-
368
- shader_bvh_extract_instance_leaves.dispatchThreads({
369
- encoder,
370
- thread_count_x: pass_data.element_count,
371
- bindings: {
372
- settings: encoder.allocateTransientValueBuffer(
373
- BVH_BUILD_SETTINGS_STRUCT,
374
- { element_count: pass_data.element_count }
375
- ),
376
- rows: resources.get(pass_data.rows),
377
- scene_database: resources.get(pass_data.scene_database),
378
- leaf_bounds: resources.get(pass_data.leaf_bounds),
379
- leaf_payload: resources.get(pass_data.leaf_payload),
380
- scene_bounds,
381
- }
382
- });
383
- }
1
+ import { assert } from "../../../core/assert.js";
2
+ import { BVH } from "../../../core/bvh2/bvh3/BVH.js";
3
+ import { FrameGraph } from "../../../engine/graphics/render/frame_graph/FrameGraph.js";
4
+ import { BufferResourceDescriptor } from "../../device/graph/BufferResourceDescriptor.js";
5
+ import { ShadeGPUCommandContext } from "../../device/ShadeGPUCommandContext.js";
6
+ import { ensure_buffer_capacity } from "../geometry/make_temp_gpu_buffer.js";
7
+ import { bvh_buffer_size } from "../gpu_primitive/bvh/BVH_BUFFER_LAYOUT.js";
8
+ import { graph_bvh_build_lbvh } from "../gpu_primitive/bvh/graph_bvh_build_lbvh.js";
9
+ import { shader_bvh_extract_instance_leaves } from "./shader_bvh_extract_instance_leaves.js";
10
+
11
+ /**
12
+ * `root = BVH_NULL_NODE` — an empty tree, in the four bytes every consumer already reads that way.
13
+ * @type {Uint32Array}
14
+ */
15
+ const EMPTY_TREE = Uint32Array.from([0xffffffff]);
16
+
17
+ /**
18
+ * The scene-bounds cell before anything has been merged into it: +inf for the three minima, -inf
19
+ * for the three maxima, so the first contribution wins on every axis.
20
+ *
21
+ * Written host-side as exact u32 bit patterns. A pool-cleared buffer holds zeroes, and zero is a
22
+ * perfectly good coordinate a scene entirely in the positive octant would end up with bounds
23
+ * anchored at the origin and every Morton code crushed into a corner of the grid.
24
+ *
25
+ * @type {Uint32Array}
26
+ */
27
+ const SCENE_BOUNDS_SEED = Uint32Array.from([
28
+ 0x7F800000, 0x7F800000, 0x7F800000,
29
+ 0xFF800000, 0xFF800000, 0xFF800000,
30
+ ]);
31
+
32
+ /**
33
+ * Top-Level Acceleration Structure (TLAS)
34
+ */
35
+ export class GPUInstancesAccelerationStructure {
36
+
37
+ /**
38
+ * @type {GraphicsContext}
39
+ */
40
+ #graphics
41
+
42
+ /**
43
+ * @type {GPUDevice}
44
+ */
45
+ #device
46
+
47
+ #bvh = new BVH();
48
+
49
+ /**
50
+ * The CPU-side tree. Still maintained incrementally by the `instance_*` methods and still walked
51
+ * by CPU queries {@link DirectionalLightShadowmap} runs `compute_tight_near_far_clipping_planes`
52
+ * against it per cascade per frame. What the GPU build retires is the per-frame treelet pass and
53
+ * the full flatten-and-upload, not the tree.
54
+ */
55
+ get bvh() {
56
+ return this.#bvh;
57
+ }
58
+
59
+ clear() {
60
+ this.#bvh.release_all();
61
+ this.#node_mapping.clear();
62
+ this.#membership_version++;
63
+ this.#version++;
64
+ }
65
+
66
+ /**
67
+ * @type {GPUBuffer}
68
+ */
69
+ #buffer
70
+
71
+ /**
72
+ *
73
+ * @return {GPUBuffer}
74
+ */
75
+ get buffer() {
76
+ return this.#buffer;
77
+ }
78
+
79
+ #gpu_version = 0;
80
+ #version = 0;
81
+
82
+ /**
83
+ * Bumped when the set of live rows changes — an add or a remove — and not when one merely moves.
84
+ * The rows list is uploaded only when this moves, so a scene in continuous motion re-uploads
85
+ * nothing.
86
+ *
87
+ * @type {number}
88
+ */
89
+ #membership_version = 0;
90
+
91
+ /**
92
+ * Membership version the {@link #rows_buffer} currently holds.
93
+ * @type {number}
94
+ */
95
+ #rows_gpu_version = -1;
96
+
97
+ /**
98
+ * Compact mirror of the live `meshes` rows, in insertion order. Rebuilt from
99
+ * {@link #node_mapping} when membership churns.
100
+ *
101
+ * @type {Uint32Array}
102
+ */
103
+ #rows = new Uint32Array(0);
104
+
105
+ /**
106
+ * @type {GPUBuffer|undefined}
107
+ */
108
+ #rows_buffer
109
+
110
+ /**
111
+ *
112
+ * @param {GraphicsContext} graphics
113
+ */
114
+ constructor(graphics) {
115
+ assert.defined(graphics, 'graphics');
116
+ assert.equal(graphics.isGraphicsContext, true, 'graphics.isGraphicsContext !== true');
117
+
118
+ const device = graphics.device;
119
+
120
+ this.#graphics = graphics;
121
+ this.#device = device;
122
+
123
+ this.#buffer = device.createBuffer({
124
+ label: 'TLAS',
125
+ size: 1024,
126
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
127
+ });
128
+ }
129
+
130
+ /**
131
+ *
132
+ * @type {Map<number, number>}
133
+ */
134
+ #node_mapping = new Map();
135
+
136
+ /**
137
+ *
138
+ * @param {number} index
139
+ * @param {Mesh} instance
140
+ */
141
+ instance_add(index, instance) {
142
+ assert.isNonNegativeInteger(index, 'index');
143
+ assert.defined(instance, 'instance');
144
+
145
+ const bvh = this.#bvh;
146
+
147
+ const node = bvh.allocate_node();
148
+ bvh.node_set_user_data(node, index);
149
+ bvh.node_set_aabb(node, instance.bounding_box);
150
+
151
+ bvh.insert_leaf(node);
152
+
153
+ this.#node_mapping.set(index, node);
154
+
155
+ this.#membership_version++;
156
+ this.#version++;
157
+ }
158
+
159
+ /**
160
+ * Drop an instance previously handed to {@link instance_add}. The leaf is unlinked and its node
161
+ * returned to the pool, so the tree stays proportional to what is in the scene rather than to
162
+ * everything that ever was.
163
+ *
164
+ * @param {number} index
165
+ */
166
+ instance_remove(index) {
167
+ assert.isNonNegativeInteger(index, 'index');
168
+
169
+ const node = this.#node_mapping.get(index);
170
+
171
+ assert.defined(node, 'node');
172
+
173
+ const bvh = this.#bvh;
174
+
175
+ bvh.remove_leaf(node);
176
+ bvh.release_node(node);
177
+
178
+ this.#node_mapping.delete(index);
179
+
180
+ this.#membership_version++;
181
+ this.#version++;
182
+ }
183
+
184
+ /**
185
+ *
186
+ * @param {number} index
187
+ * @param {Mesh} instance
188
+ */
189
+ instance_update(index, instance) {
190
+ assert.isNonNegativeInteger(index, 'index');
191
+ assert.defined(instance, 'instance');
192
+
193
+ const node = this.#node_mapping.get(index);
194
+
195
+ this.#bvh.node_move_aabb(node, instance.bounding_box);
196
+
197
+ this.#version++;
198
+ }
199
+
200
+ /**
201
+ * Bring {@link #rows_buffer} in line with the live row set, if and only if membership changed.
202
+ *
203
+ * @returns {number} number of live rows
204
+ */
205
+ #refresh_rows() {
206
+ const count = this.#node_mapping.size;
207
+
208
+ if (this.#rows_gpu_version === this.#membership_version && this.#rows.length >= count) {
209
+ return count;
210
+ }
211
+
212
+ if (this.#rows.length < count) {
213
+ this.#rows = new Uint32Array(count);
214
+ }
215
+
216
+ let i = 0;
217
+ for (const row of this.#node_mapping.keys()) {
218
+ this.#rows[i] = row;
219
+ i++;
220
+ }
221
+
222
+ const byte_size = Math.max(4, count * Uint32Array.BYTES_PER_ELEMENT);
223
+
224
+ if (this.#rows_buffer === undefined) {
225
+ this.#rows_buffer = this.#device.createBuffer({
226
+ label: 'TLAS/rows',
227
+ size: Math.max(1024, byte_size),
228
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
229
+ });
230
+ } else {
231
+ this.#rows_buffer = ensure_buffer_capacity(this.#device, this.#rows_buffer, byte_size);
232
+ }
233
+
234
+ // Queue writes land in submission order ahead of command buffers submitted after them, so
235
+ // the build encoded below sees these rows. Offset and size are in elements of the source,
236
+ // per `GPUQueue.writeBuffer` `#rows` can be longer than the live set.
237
+ this.#device.queue.writeBuffer(this.#rows_buffer, 0, this.#rows, 0, count);
238
+
239
+ this.#rows_gpu_version = this.#membership_version;
240
+
241
+ return count;
242
+ }
243
+
244
+ /**
245
+ * Build the tree, from the world AABBs the scene database holds.
246
+ *
247
+ * @param {GPUBuffer} scene_database_buffer
248
+ */
249
+ #build(scene_database_buffer) {
250
+ assert.defined(scene_database_buffer, 'scene_database_buffer');
251
+
252
+ const device = this.#device;
253
+
254
+ const element_count = this.#node_mapping.size;
255
+
256
+ // `ensure_buffer_capacity` can hand back a NEW buffer and destroy the old one. Consumers are
257
+ // safe because they read `tlas.buffer` per frame at pass-execute time but the field has to
258
+ // be reassigned before the graph imports it.
259
+ this.#buffer = ensure_buffer_capacity(
260
+ device,
261
+ this.#buffer,
262
+ bvh_buffer_size(Math.max(1, element_count)),
263
+ 1024,
264
+ 1024,
265
+ 1.2
266
+ );
267
+
268
+ if (element_count === 0) {
269
+ device.queue.writeBuffer(this.#buffer, 0, EMPTY_TREE);
270
+
271
+ return;
272
+ }
273
+
274
+ this.#refresh_rows();
275
+
276
+ const graph = new FrameGraph('TLAS build');
277
+
278
+ const rows = graph.import_resource(
279
+ "tlas/rows",
280
+ BufferResourceDescriptor.fromBuffer(this.#rows_buffer),
281
+ this.#rows_buffer
282
+ );
283
+
284
+ const scene_database = graph.import_resource(
285
+ "scene database",
286
+ BufferResourceDescriptor.fromBuffer(scene_database_buffer),
287
+ scene_database_buffer
288
+ );
289
+
290
+ const nodes = graph.import_resource(
291
+ "tlas/nodes",
292
+ BufferResourceDescriptor.fromBuffer(this.#buffer),
293
+ this.#buffer
294
+ );
295
+
296
+ const extract_data = {};
297
+ const extract_pass = graph.add("tlas/extract instance leaves", extract_data, extract_execute);
298
+
299
+ extract_data.element_count = element_count;
300
+ extract_data.rows = extract_pass.read(rows);
301
+ extract_data.scene_database = extract_pass.read(scene_database);
302
+
303
+ extract_data.leaf_bounds = extract_pass.create("tlas/leaf bounds", BufferResourceDescriptor.from(
304
+ element_count * 6 * Float32Array.BYTES_PER_ELEMENT,
305
+ GPUBufferUsage.STORAGE
306
+ ));
307
+
308
+ extract_data.leaf_payload = extract_pass.create("tlas/leaf payload", BufferResourceDescriptor.from(
309
+ element_count * Uint32Array.BYTES_PER_ELEMENT,
310
+ GPUBufferUsage.STORAGE
311
+ ));
312
+
313
+ extract_data.scene_bounds = extract_pass.create("tlas/scene bounds", BufferResourceDescriptor.from(
314
+ SCENE_BOUNDS_SEED.byteLength,
315
+ GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
316
+ ));
317
+
318
+ graph_bvh_build_lbvh({
319
+ graph,
320
+ leaf_bounds: extract_data.leaf_bounds,
321
+ leaf_payload: extract_data.leaf_payload,
322
+ scene_bounds: extract_data.scene_bounds,
323
+ element_count,
324
+ nodes,
325
+ });
326
+
327
+ const cmd = ShadeGPUCommandContext.create(this.#graphics, 'TLAS/build');
328
+
329
+ cmd.encodeGraph(graph);
330
+ cmd.finish();
331
+ }
332
+
333
+ /**
334
+ * @param {GPUBuffer} scene_database_buffer the table the world AABBs are read from
335
+ */
336
+ push_to_gpu(scene_database_buffer) {
337
+ this.#build(scene_database_buffer);
338
+
339
+ this.#gpu_version = this.#version;
340
+ }
341
+
342
+ /**
343
+ * @param {GPUBuffer} scene_database_buffer
344
+ */
345
+ update(scene_database_buffer) {
346
+ if (this.#gpu_version === this.#version) {
347
+ return;
348
+ }
349
+
350
+ this.push_to_gpu(scene_database_buffer);
351
+ }
352
+ }
353
+
354
+ /**
355
+ * @param pass_data
356
+ * @param {FramePassResources} resources
357
+ * @param {GraphicsExecutionContext} context
358
+ */
359
+ function extract_execute(pass_data, resources, context) {
360
+ const encoder = context.encoder;
361
+
362
+ const scene_bounds = resources.get(pass_data.scene_bounds);
363
+
364
+ // Seeded rather than cleared: the merge is a min/max, and zero is not an identity for either.
365
+ encoder.writeBuffer(scene_bounds, 0, SCENE_BOUNDS_SEED.buffer, 0, SCENE_BOUNDS_SEED.byteLength);
366
+
367
+ shader_bvh_extract_instance_leaves.dispatchThreads({
368
+ encoder,
369
+ thread_count_x: pass_data.element_count,
370
+ bindings: {
371
+ settings: { element_count: pass_data.element_count },
372
+ rows: resources.get(pass_data.rows),
373
+ scene_database: resources.get(pass_data.scene_database),
374
+ leaf_bounds: resources.get(pass_data.leaf_bounds),
375
+ leaf_payload: resources.get(pass_data.leaf_payload),
376
+ scene_bounds,
377
+ }
378
+ });
379
+ }