@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.
- package/package.json +1 -1
- package/src/engine/graphics3/decal/GPUDecalRenderer.js +3 -3
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.js +4 -2
- package/src/engine/graphics3/highlight/GPUHighlightRenderer.d.ts.map +1 -1
- package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +2 -3
- package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/RENDERER_CONTRACT.md +2 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +18 -0
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +73 -0
- package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +750 -0
- package/src/shade/device/ShadeGPUCommandContext.d.ts +10 -16
- package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
- package/src/shade/device/ShadeGPUCommandContext.js +801 -994
- package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts +107 -0
- package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts.map +1 -0
- package/src/shade/device/pass/ShadeGPUComputePassEncoder.js +222 -0
- package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts +168 -0
- package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts.map +1 -0
- package/src/shade/device/pass/ShadeGPURenderPassEncoder.js +317 -0
- package/src/shade/device/timing/GPUTimerArray.d.ts +4 -9
- package/src/shade/device/timing/GPUTimerArray.d.ts.map +1 -1
- package/src/shade/device/timing/GPUTimerArray.js +261 -289
- package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +20 -2
- package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts +59 -0
- package/src/shade/device/timing/ShadeGPUContextProfiler.d.ts.map +1 -0
- package/src/shade/device/timing/ShadeGPUContextProfiler.js +182 -0
- package/src/shade/device/timing/profile/GPUProfileSession.d.ts +4 -4
- package/src/shade/device/timing/profile/GPUProfileSession.js +4 -4
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.js +3 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_points.js +3 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_visibility.js +3 -1
- package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +2 -2
- package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +2 -2
- package/src/shade/renderer/Renderer.d.ts +0 -6
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +0 -29
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +1 -3
- package/src/shade/renderer/animation/shader_animation_tick.d.ts.map +1 -1
- package/src/shade/renderer/animation/shader_animation_tick.js +128 -125
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +8 -18
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_geometry_sphere_derive.js +100 -98
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.js +215 -212
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_scatter.js +135 -120
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_skinned_mesh_bounds_refresh.js +77 -75
- package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +375 -371
- package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +3 -3
- package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.js +1 -1
- package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/GPUDatabase.js +14 -19
- package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/gpu_table_element_upload_shader.js +7 -2
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +325 -319
- package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
- package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +3 -1
- package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_tonemap_HDR.js +4 -1
- package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts +2 -2
- package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts.map +1 -1
- package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
- package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +3 -3
- package/src/shade/renderer/fow/shader_fog_of_war.d.ts.map +1 -1
- package/src/shade/renderer/fow/shader_fog_of_war.js +3 -1
- package/src/shade/renderer/geometry/bvh/record_blas_refit.js +102 -102
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts.map +1 -1
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.js +125 -121
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +766 -774
- package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/shader_meshlet_metadata_address_patch.js +72 -69
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +5 -10
- package/src/shade/renderer/geometry/sdf/shader_build_sdf.js +129 -129
- package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.js +5 -3
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +4 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_resolve_probes.js +3 -1
- package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/clipmap/shader_update_clipmap_cascade.js +114 -112
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.js +4 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.js +187 -184
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.js +4 -1
- package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.js +6 -8
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +3 -1
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.js +3 -1
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +3 -3
- package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +3 -3
- package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +217 -217
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +145 -142
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +87 -82
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.js +143 -140
- package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts +2 -2
- package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/verify_gpu_bvh_build.js +43 -8
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +4 -5
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +88 -84
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +194 -191
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +33 -69
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +6 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +1 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.js +23 -7
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/execute_filter_environment_map.js +1 -2
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/shader_convolve_reflection_map.js +6 -1
- package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.js +234 -219
- package/src/shade/renderer/lightmap/bake/raster/shader_lightmap_to_viz_buffer.js +2 -2
- package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.js +191 -191
- package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/tile/shader_lightmap_accummulate_tile.js +85 -82
- package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles.js +5 -3
- package/src/shade/renderer/particles/prototypeParticleSystem.js +3 -4
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +132 -117
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +79 -77
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +111 -99
- package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts.map +1 -1
- package/src/shade/renderer/particles/sort/shader_particle_sort.js +187 -158
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +7 -10
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +4 -1
- package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/bloom/shader_bloom_mix.js +3 -1
- package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +4 -2
- package/src/shade/renderer/postprocess/denoise/fragment_shader_denoise_ao.js +147 -147
- package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +121 -119
- package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +1 -2
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +4 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +4 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +4 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +4 -1
- package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +2 -4
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +4 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +4 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch.js +4 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +269 -266
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +273 -270
- package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +4 -1
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +8 -11
- package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.js +5 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +11 -8
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +7 -8
- package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/motion_blur/shader_motion_blur_reconstruct.js +3 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_concat.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/nss/shader_nss_concat.js +70 -68
- package/src/shade/renderer/postprocess/ssr/depth_max_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/depth_max_shader.js +70 -68
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.js +3 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.js +4 -1
- package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.js +103 -101
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +4 -2
- package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_trace_shader.js +3 -1
- package/src/shade/renderer/postprocess/taa/shader_taa.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/taa/shader_taa.js +4 -1
- package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +5 -5
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +339 -341
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +114 -109
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +118 -115
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +69 -65
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +722 -722
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +1 -9
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +1 -6
- package/src/shade/renderer/restir/di/graph_restir_di.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/graph_restir_di.js +2 -3
- package/src/shade/renderer/restir/di/graph_restir_di_denoise.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/graph_restir_di_denoise.js +1 -2
- package/src/shade/renderer/restir/di/shader_restir_di_denoise.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_denoise.js +139 -136
- package/src/shade/renderer/restir/di/shader_restir_di_resample.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_resample.js +131 -129
- package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +101 -99
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +379 -383
- package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts.map +1 -1
- package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +147 -144
- package/src/shade/renderer/shader/ComputeShader.d.ts +2 -2
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +14 -17
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts +2 -2
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +189 -189
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +3 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +14 -18
- package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/shader_shadowmap_remap_cube_to_octahedral.js +5 -1
- package/src/shade/renderer/shadow/ray/shader_shadow_upscale.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/shader_shadow_upscale.js +3 -1
- package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +73 -73
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +151 -148
- package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +4 -2
- package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/trace/shader_trace_rays.js +18 -4
- package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +7 -8
- package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/cascade/shader_build_scene_sdf_f32.js +6 -2
- package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_debug_viz.js +129 -127
- package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.js +5 -3
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +2 -5
- package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +233 -231
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +2 -4
- package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
- package/src/shade/wgsl/validate_wgsl_source.js +8 -3
- package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts +0 -21
- package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts.map +0 -1
- package/src/shade/device/timing/profile/make_profiling_pass_encoder.js +0 -114
- package/src/shade/device/timing/profile/parse_workgroup_size.d.ts +0 -20
- package/src/shade/device/timing/profile/parse_workgroup_size.d.ts.map +0 -1
- package/src/shade/device/timing/profile/parse_workgroup_size.js +0 -43
|
@@ -1,775 +1,767 @@
|
|
|
1
|
-
import { assert } from "../../../../core/assert.js";
|
|
2
|
-
import { ALLOCATOR_NO_SPACE, OffsetAllocator } from "../../../../core/binary/allocator/OffsetAllocator.js";
|
|
3
|
-
import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
|
|
4
|
-
import { platform_compute_endianness } from "../../../../core/binary/platform_compute_endianness.js";
|
|
5
|
-
import Signal from "../../../../core/events/signal/Signal.js";
|
|
6
|
-
import { MEGABYTE } from "../../../../core/science/units/memory/MEGABYTE.js";
|
|
7
|
-
import { read_wgsl_type_value } from "../../shader/type/serde/read_gpu_typed_buffer.js";
|
|
8
|
-
import { write_wgsl_type_value } from "../../shader/type/serde/write_gpu_typed_buffer.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from "
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
*
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
*
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
*
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
*
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
*
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
*
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
*
|
|
135
|
-
* @param {
|
|
136
|
-
* @param {number} [
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
assert.isNonNegativeInteger(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
assert.greaterThan(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
this.#
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
this.#
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
*
|
|
183
|
-
* @param {number}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
assert.isNonNegativeInteger(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
current_buffer_size_words +
|
|
212
|
-
current_buffer_size_words
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
current_metadata_buffer_size_elements +
|
|
224
|
-
current_metadata_buffer_size_elements
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
*
|
|
237
|
-
* @param {
|
|
238
|
-
* @param {number}
|
|
239
|
-
* @param {number}
|
|
240
|
-
* @param {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
*
|
|
278
|
-
* @param {number}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
assert.isNonNegativeInteger(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
//
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
assert.notEqual(
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
//
|
|
349
|
-
//
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
record.
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
record.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
this.#
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
this.#
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
* @param {number}
|
|
404
|
-
* @
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
let
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
data_allocation.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
metadata_allocation.
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
let
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
*
|
|
459
|
-
* @
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
record.
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
record.
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
this.#
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
this.#
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
*
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
*
|
|
539
|
-
* @
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
assert.
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
record.
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
record.
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
//
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
//
|
|
563
|
-
//
|
|
564
|
-
//
|
|
565
|
-
//
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
*
|
|
577
|
-
*
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
const
|
|
592
|
-
const
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
//
|
|
597
|
-
//
|
|
598
|
-
//
|
|
599
|
-
//
|
|
600
|
-
// —
|
|
601
|
-
//
|
|
602
|
-
//
|
|
603
|
-
//
|
|
604
|
-
//
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
const
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
let
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
//
|
|
616
|
-
//
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
data_regions_array[region_words]
|
|
620
|
-
data_regions_array[region_words +
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
metadata_regions_array[region_words]
|
|
624
|
-
metadata_regions_array[region_words +
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
//
|
|
657
|
-
//
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
let
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
//
|
|
665
|
-
//
|
|
666
|
-
//
|
|
667
|
-
//
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
patches_array[p++] =
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
if (this.#meshlet_metadata_buffer) {
|
|
770
|
-
result += this.#meshlet_metadata_buffer.size;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
return result;
|
|
774
|
-
}
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { ALLOCATOR_NO_SPACE, OffsetAllocator } from "../../../../core/binary/allocator/OffsetAllocator.js";
|
|
3
|
+
import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
|
|
4
|
+
import { platform_compute_endianness } from "../../../../core/binary/platform_compute_endianness.js";
|
|
5
|
+
import Signal from "../../../../core/events/signal/Signal.js";
|
|
6
|
+
import { MEGABYTE } from "../../../../core/science/units/memory/MEGABYTE.js";
|
|
7
|
+
import { read_wgsl_type_value } from "../../shader/type/serde/read_gpu_typed_buffer.js";
|
|
8
|
+
import { write_wgsl_type_value } from "../../shader/type/serde/write_gpu_typed_buffer.js";
|
|
9
|
+
import { inspect_gpu_buffer_typed } from "../../buffer/inspect_gpu_buffer_typed.js";
|
|
10
|
+
import {
|
|
11
|
+
BUFFER_INTRA_COPY_REGION_STRUCT,
|
|
12
|
+
shader_buffer_intra_copy_regions
|
|
13
|
+
} from "../../buffer/util/shader_buffer_intra_copy_regions.js";
|
|
14
|
+
import { MESHLET_METADATA_STRUCT } from "./encoding/MESHLET_METADATA_STRUCT.js";
|
|
15
|
+
import { shader_meshlet_metadata_address_patch } from "./shader_meshlet_metadata_address_patch.js";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* In meshlets
|
|
19
|
+
* @type {number}
|
|
20
|
+
*/
|
|
21
|
+
const DEFAULT_METADATA_CAPACITY = 128 * 1024;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* In bytes
|
|
25
|
+
* @type {number}
|
|
26
|
+
*/
|
|
27
|
+
const DEFAULT_DATA_CAPACITY = 32 * MEGABYTE;
|
|
28
|
+
|
|
29
|
+
class MeshletBatchAllocationRecord {
|
|
30
|
+
/**
|
|
31
|
+
* @type {Allocation}
|
|
32
|
+
*/
|
|
33
|
+
metadata
|
|
34
|
+
/**
|
|
35
|
+
* @type {Allocation}
|
|
36
|
+
*/
|
|
37
|
+
data
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Number of words
|
|
41
|
+
* @type {number}
|
|
42
|
+
*/
|
|
43
|
+
data_size = 0;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Meshlet count
|
|
47
|
+
* @type {number}
|
|
48
|
+
*/
|
|
49
|
+
meshlet_count = 0;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @type {ArrayBuffer}
|
|
54
|
+
*/
|
|
55
|
+
metadata_buffer_original;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* @type {Signal<>}
|
|
60
|
+
*/
|
|
61
|
+
changed = new Signal()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class GPUMeshletManager {
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Allocation sizes in words of 4 bytes
|
|
68
|
+
* @type {OffsetAllocator}
|
|
69
|
+
*/
|
|
70
|
+
#allocator_data = new OffsetAllocator(1024);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Allocation sizes in meshlets
|
|
74
|
+
* @type {OffsetAllocator}
|
|
75
|
+
*/
|
|
76
|
+
#allocator_metadata = new OffsetAllocator(1024);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @type {GPUBuffer}
|
|
80
|
+
*/
|
|
81
|
+
#meshlet_data_buffer;
|
|
82
|
+
|
|
83
|
+
get buffer_data() {
|
|
84
|
+
return this.#meshlet_data_buffer;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @type {GPUBuffer}
|
|
89
|
+
*/
|
|
90
|
+
#meshlet_metadata_buffer;
|
|
91
|
+
|
|
92
|
+
get buffer_metadata() {
|
|
93
|
+
return this.#meshlet_metadata_buffer;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @type {GPUDevice}
|
|
98
|
+
*/
|
|
99
|
+
#device;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
*
|
|
103
|
+
* @type {number}
|
|
104
|
+
*/
|
|
105
|
+
#deallocations_since_last_rebuild = 0;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
*
|
|
109
|
+
* @type {MeshletBatchAllocationRecord[]}
|
|
110
|
+
*/
|
|
111
|
+
#records = [];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Queue of GPU-side clones that have been allocated but not yet
|
|
115
|
+
* copied + patched. Drained by {@link update}. Each entry holds the
|
|
116
|
+
* minimum bookkeeping needed to issue two `copyBufferToBuffer`
|
|
117
|
+
* commands and N `(record_index, address_delta)` patch entries.
|
|
118
|
+
*
|
|
119
|
+
* Entries name the two records, not the addresses they held when the
|
|
120
|
+
* clone was queued: a {@link compact} or {@link grow} in between
|
|
121
|
+
* migrates both, and {@link update} reads where they ended up. What
|
|
122
|
+
* an entry does require is that neither record is handed back to
|
|
123
|
+
* {@link remove_batch} before the flush.
|
|
124
|
+
*
|
|
125
|
+
* @type {{
|
|
126
|
+
* source: MeshletBatchAllocationRecord,
|
|
127
|
+
* clone: MeshletBatchAllocationRecord,
|
|
128
|
+
* }[]}
|
|
129
|
+
*/
|
|
130
|
+
#pending_clones = [];
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
*
|
|
134
|
+
* @param {GPUDevice} device
|
|
135
|
+
* @param {number} [initial_data_capacity] in bytes
|
|
136
|
+
* @param {number} [initial_metadata_capacity] in meshlets
|
|
137
|
+
*/
|
|
138
|
+
constructor({
|
|
139
|
+
device,
|
|
140
|
+
initial_data_capacity = DEFAULT_DATA_CAPACITY,
|
|
141
|
+
initial_metadata_capacity = DEFAULT_METADATA_CAPACITY,
|
|
142
|
+
}) {
|
|
143
|
+
assert.defined(device, 'device');
|
|
144
|
+
|
|
145
|
+
assert.isNonNegativeInteger(initial_data_capacity, 'initial_data_capacity');
|
|
146
|
+
assert.isNonNegativeInteger(initial_metadata_capacity, 'initial_metadata_capacity');
|
|
147
|
+
|
|
148
|
+
assert.greaterThan(initial_data_capacity, 0, 'initial_data_capacity');
|
|
149
|
+
assert.greaterThan(initial_metadata_capacity, 0, 'initial_data_capacity');
|
|
150
|
+
|
|
151
|
+
this.#device = device;
|
|
152
|
+
|
|
153
|
+
const data_buffer_size_words = Math.ceil(initial_data_capacity / 4);
|
|
154
|
+
|
|
155
|
+
// TODO manage max-allocations as well
|
|
156
|
+
this.#allocator_data = new OffsetAllocator(data_buffer_size_words);
|
|
157
|
+
this.#allocator_metadata = new OffsetAllocator(initial_metadata_capacity);
|
|
158
|
+
|
|
159
|
+
this.#meshlet_data_buffer = device.createBuffer({
|
|
160
|
+
label: 'GPUMeshletManager/data',
|
|
161
|
+
size: data_buffer_size_words * 4,
|
|
162
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
this.#meshlet_metadata_buffer = device.createBuffer({
|
|
166
|
+
label: 'GPUMeshletManager/metadata',
|
|
167
|
+
size: initial_metadata_capacity * MESHLET_METADATA_STRUCT.aligned_size,
|
|
168
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
compact() {
|
|
174
|
+
this.#rebuild(
|
|
175
|
+
this.#meshlet_data_buffer.size >>> 2,
|
|
176
|
+
Math.ceil(this.#meshlet_metadata_buffer.size / MESHLET_METADATA_STRUCT.aligned_size)
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
*
|
|
182
|
+
* @param {number} extra_data_size in words (4 bytes)
|
|
183
|
+
* @param {number} extra_metadata_size in metadata elements
|
|
184
|
+
*/
|
|
185
|
+
grow(extra_data_size, extra_metadata_size) {
|
|
186
|
+
assert.isNonNegativeInteger(extra_data_size, 'extra_data_size');
|
|
187
|
+
assert.isNonNegativeInteger(extra_metadata_size, 'extra_metadata_size');
|
|
188
|
+
|
|
189
|
+
if (extra_data_size === 0 && extra_metadata_size === 0) {
|
|
190
|
+
// nothing to do
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const current_data_buffer_size_bytes = this.#meshlet_data_buffer.size;
|
|
195
|
+
const current_metadata_buffer_size = this.#meshlet_metadata_buffer.size;
|
|
196
|
+
|
|
197
|
+
const current_buffer_size_words = current_data_buffer_size_bytes >> 2;
|
|
198
|
+
const current_metadata_buffer_size_elements = Math.ceil(current_metadata_buffer_size / MESHLET_METADATA_STRUCT.aligned_size);
|
|
199
|
+
|
|
200
|
+
const DATA_GROWTH_STEP = 16 * 1024;
|
|
201
|
+
const METADATA_GROWTH_STEP = 256;
|
|
202
|
+
const GROWTH_MULTIPLIER = 1.25;
|
|
203
|
+
|
|
204
|
+
let new_data_size;
|
|
205
|
+
if (extra_data_size === 0) {
|
|
206
|
+
new_data_size = current_buffer_size_words;
|
|
207
|
+
} else {
|
|
208
|
+
// grow
|
|
209
|
+
new_data_size = Math.max(
|
|
210
|
+
current_buffer_size_words + extra_data_size,
|
|
211
|
+
current_buffer_size_words + DATA_GROWTH_STEP,
|
|
212
|
+
Math.ceil(current_buffer_size_words * GROWTH_MULTIPLIER)
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let new_metadata_size;
|
|
217
|
+
if (extra_metadata_size === 0) {
|
|
218
|
+
new_metadata_size = current_metadata_buffer_size_elements;
|
|
219
|
+
} else {
|
|
220
|
+
// grow
|
|
221
|
+
new_metadata_size = Math.max(
|
|
222
|
+
current_metadata_buffer_size_elements + extra_metadata_size,
|
|
223
|
+
current_metadata_buffer_size_elements + METADATA_GROWTH_STEP,
|
|
224
|
+
current_metadata_buffer_size_elements * GROWTH_MULTIPLIER
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
this.#rebuild(
|
|
229
|
+
new_data_size,
|
|
230
|
+
new_metadata_size
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Helper to patch pointers in metadata and upload to GPU
|
|
236
|
+
* @param {ArrayBuffer} source_array_buffer
|
|
237
|
+
* @param {number} meshlet_count
|
|
238
|
+
* @param {number} data_offset_words
|
|
239
|
+
* @param {number} metadata_offset_index
|
|
240
|
+
* @param {GPUBuffer} target_buffer
|
|
241
|
+
*/
|
|
242
|
+
#write_patched_metadata(
|
|
243
|
+
source_array_buffer,
|
|
244
|
+
meshlet_count,
|
|
245
|
+
data_offset_words,
|
|
246
|
+
metadata_offset_index,
|
|
247
|
+
target_buffer
|
|
248
|
+
) {
|
|
249
|
+
const temp_writer = BinaryBuffer.fromEndianness(platform_compute_endianness());
|
|
250
|
+
temp_writer.setCapacity(meshlet_count * MESHLET_METADATA_STRUCT.size); // pre-allocate to avoid resizing
|
|
251
|
+
|
|
252
|
+
const source_reader = BinaryBuffer.fromArrayBuffer(source_array_buffer);
|
|
253
|
+
source_reader.endianness = platform_compute_endianness();
|
|
254
|
+
|
|
255
|
+
// Iterate over meshlets in the batch, patch the address, and write to temp buffer
|
|
256
|
+
for (let i = 0; i < meshlet_count; i++) {
|
|
257
|
+
const header = read_wgsl_type_value(source_reader, MESHLET_METADATA_STRUCT);
|
|
258
|
+
|
|
259
|
+
// PATCH: Add the allocation offset to the relative address
|
|
260
|
+
header.address += data_offset_words;
|
|
261
|
+
|
|
262
|
+
write_wgsl_type_value(header, temp_writer, MESHLET_METADATA_STRUCT);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Upload
|
|
266
|
+
this.#device.queue.writeBuffer(
|
|
267
|
+
target_buffer,
|
|
268
|
+
metadata_offset_index * MESHLET_METADATA_STRUCT.aligned_size,
|
|
269
|
+
temp_writer.data,
|
|
270
|
+
0,
|
|
271
|
+
meshlet_count * MESHLET_METADATA_STRUCT.aligned_size
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
*
|
|
277
|
+
* @param {number} new_data_size
|
|
278
|
+
* @param {number} new_metadata_size
|
|
279
|
+
*/
|
|
280
|
+
#rebuild(
|
|
281
|
+
new_data_size,
|
|
282
|
+
new_metadata_size
|
|
283
|
+
) {
|
|
284
|
+
|
|
285
|
+
assert.isNonNegativeInteger(new_data_size, 'new_data_size');
|
|
286
|
+
assert.isNonNegativeInteger(new_metadata_size, 'new_metadata_size');
|
|
287
|
+
|
|
288
|
+
// Outstanding clone work survives this. A queued clone names its
|
|
289
|
+
// source and destination records, both of which are migrated
|
|
290
|
+
// below, and the flush reads their addresses when it runs — so a
|
|
291
|
+
// rebuild moves the copy rather than invalidating it.
|
|
292
|
+
|
|
293
|
+
// console.warn('GPUMeshletManager/rebuild');
|
|
294
|
+
|
|
295
|
+
const device = this.#device;
|
|
296
|
+
|
|
297
|
+
const records = this.#records;
|
|
298
|
+
const record_count = records.length;
|
|
299
|
+
const new_allocator_data = new OffsetAllocator(
|
|
300
|
+
new_data_size,
|
|
301
|
+
Math.max(record_count * 2, 128 * 1024)
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
const old_buffer_data = this.#meshlet_data_buffer;
|
|
305
|
+
const new_buffer_data = device.createBuffer({
|
|
306
|
+
label: old_buffer_data.label,
|
|
307
|
+
usage: old_buffer_data.usage,
|
|
308
|
+
size: new_data_size * 4,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const new_allocator_metadata = new OffsetAllocator(
|
|
312
|
+
new_metadata_size,
|
|
313
|
+
Math.max(record_count * 2, 128 * 1024)
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
const old_buffer_metadata = this.#meshlet_metadata_buffer;
|
|
317
|
+
const new_buffer_metadata = device.createBuffer({
|
|
318
|
+
label: old_buffer_metadata.label,
|
|
319
|
+
usage: old_buffer_metadata.usage,
|
|
320
|
+
size: new_metadata_size * MESHLET_METADATA_STRUCT.aligned_size,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
const encoder = device.createCommandEncoder({
|
|
324
|
+
label: "GPUMeshletManager/rebuild",
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
const moved_records = [];
|
|
328
|
+
|
|
329
|
+
// move data
|
|
330
|
+
for (let i = 0; i < record_count; i++) {
|
|
331
|
+
const record = records[i];
|
|
332
|
+
|
|
333
|
+
const new_allocation_data = new_allocator_data.allocate(record.data_size);
|
|
334
|
+
const new_allocation_metadata = new_allocator_metadata.allocate(record.meshlet_count);
|
|
335
|
+
|
|
336
|
+
assert.notEqual(new_allocation_data.offset, ALLOCATOR_NO_SPACE);
|
|
337
|
+
assert.notEqual(new_allocation_metadata.offset, ALLOCATOR_NO_SPACE);
|
|
338
|
+
|
|
339
|
+
encoder.copyBufferToBuffer(
|
|
340
|
+
old_buffer_data, record.data.offset * 4,
|
|
341
|
+
new_buffer_data, new_allocation_data.offset * 4,
|
|
342
|
+
record.data_size * 4
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
const metadata_record_moved = record.data.offset !== new_allocation_data.offset;
|
|
346
|
+
|
|
347
|
+
// B. Patch Metadata (CPU -> GPU Write)
|
|
348
|
+
// Metadata contains `address` which points to the Data offset.
|
|
349
|
+
// Since the Data offset changed, we must re-calculate and upload the metadata.
|
|
350
|
+
// We reuse the helper to avoid code duplication.
|
|
351
|
+
this.#write_patched_metadata(
|
|
352
|
+
record.metadata_buffer_original,
|
|
353
|
+
record.meshlet_count,
|
|
354
|
+
new_allocation_data.offset, // The NEW data offset
|
|
355
|
+
new_allocation_metadata.offset, // The NEW metadata location
|
|
356
|
+
new_buffer_metadata
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
// update record
|
|
360
|
+
record.data = new_allocation_data;
|
|
361
|
+
record.metadata = new_allocation_metadata;
|
|
362
|
+
|
|
363
|
+
if (metadata_record_moved) {
|
|
364
|
+
moved_records.push(record);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
for (const record of moved_records) {
|
|
369
|
+
// notify
|
|
370
|
+
record.changed.send0();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const command_buffer = encoder.finish();
|
|
374
|
+
|
|
375
|
+
device.queue.submit([command_buffer]);
|
|
376
|
+
|
|
377
|
+
old_buffer_data.destroy();
|
|
378
|
+
old_buffer_metadata.destroy();
|
|
379
|
+
|
|
380
|
+
this.#meshlet_data_buffer = new_buffer_data;
|
|
381
|
+
this.#meshlet_metadata_buffer = new_buffer_metadata;
|
|
382
|
+
|
|
383
|
+
this.#allocator_data = new_allocator_data;
|
|
384
|
+
this.#allocator_metadata = new_allocator_metadata;
|
|
385
|
+
|
|
386
|
+
// reset count
|
|
387
|
+
this.#deallocations_since_last_rebuild = 0;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Allocate `data_size_words` in the data buffer and `meshlet_count`
|
|
392
|
+
* in the metadata buffer, retrying with compact-then-grow on failure.
|
|
393
|
+
* Throws if the third attempt still can't satisfy both. The two
|
|
394
|
+
* allocations are kept in lockstep — partial successes are released
|
|
395
|
+
* before retrying so we never leak.
|
|
396
|
+
*
|
|
397
|
+
* Compaction triggers a full {@link #rebuild} which migrates every
|
|
398
|
+
* existing allocation to a new buffer pair. Queued clone work is
|
|
399
|
+
* carried through it — {@link #pending_clones} names records, not
|
|
400
|
+
* addresses — so an allocation made while a clone is pending is safe.
|
|
401
|
+
*
|
|
402
|
+
* @param {number} data_size_words
|
|
403
|
+
* @param {number} meshlet_count
|
|
404
|
+
* @returns {{data: Allocation, metadata: Allocation}}
|
|
405
|
+
*/
|
|
406
|
+
#allocate_data_and_metadata(data_size_words, meshlet_count) {
|
|
407
|
+
let data_allocation;
|
|
408
|
+
let metadata_allocation;
|
|
409
|
+
|
|
410
|
+
for (let try_index = 0; try_index < 3; try_index++) {
|
|
411
|
+
|
|
412
|
+
data_allocation = this.#allocator_data.allocate(data_size_words);
|
|
413
|
+
metadata_allocation = this.#allocator_metadata.allocate(meshlet_count);
|
|
414
|
+
|
|
415
|
+
const data_ok = data_allocation.offset !== ALLOCATOR_NO_SPACE;
|
|
416
|
+
const metadata_ok = metadata_allocation.offset !== ALLOCATOR_NO_SPACE;
|
|
417
|
+
|
|
418
|
+
if (data_ok && metadata_ok) {
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// release partial allocation
|
|
423
|
+
if (data_ok) {
|
|
424
|
+
this.#allocator_data.free(data_allocation);
|
|
425
|
+
|
|
426
|
+
data_allocation.offset = ALLOCATOR_NO_SPACE;
|
|
427
|
+
data_allocation.metadata = ALLOCATOR_NO_SPACE;
|
|
428
|
+
}
|
|
429
|
+
if (metadata_ok) {
|
|
430
|
+
this.#allocator_metadata.free(metadata_allocation);
|
|
431
|
+
|
|
432
|
+
metadata_allocation.offset = ALLOCATOR_NO_SPACE;
|
|
433
|
+
metadata_allocation.metadata = ALLOCATOR_NO_SPACE;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (this.#deallocations_since_last_rebuild > 0) {
|
|
437
|
+
// try compaction
|
|
438
|
+
this.compact();
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
let grow_data_size = data_ok ? 0 : data_size_words;
|
|
443
|
+
let grow_metadata_size = metadata_ok ? 0 : meshlet_count;
|
|
444
|
+
|
|
445
|
+
this.grow(grow_data_size, grow_metadata_size);
|
|
446
|
+
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (data_allocation.offset === ALLOCATOR_NO_SPACE || metadata_allocation.offset === ALLOCATOR_NO_SPACE) {
|
|
450
|
+
throw new Error('Failed to allocate GPU memory for meshlet batch');
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return { data: data_allocation, metadata: metadata_allocation };
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
*
|
|
458
|
+
* @param {MeshletBatch} batch
|
|
459
|
+
* @returns {MeshletBatchAllocationRecord}
|
|
460
|
+
*/
|
|
461
|
+
#allocate_for_batch(batch) {
|
|
462
|
+
assert.defined(batch, 'batch');
|
|
463
|
+
|
|
464
|
+
const data_buffer = batch.data_buffer;
|
|
465
|
+
|
|
466
|
+
const data_size_words = Math.ceil(data_buffer.byteLength / 4);
|
|
467
|
+
|
|
468
|
+
const meshlet_count = batch.count;
|
|
469
|
+
|
|
470
|
+
const { data, metadata } = this.#allocate_data_and_metadata(data_size_words, meshlet_count);
|
|
471
|
+
|
|
472
|
+
const record = new MeshletBatchAllocationRecord();
|
|
473
|
+
|
|
474
|
+
record.data = data;
|
|
475
|
+
record.metadata = metadata;
|
|
476
|
+
|
|
477
|
+
record.meshlet_count = meshlet_count;
|
|
478
|
+
record.data_size = data_size_words;
|
|
479
|
+
|
|
480
|
+
record.metadata_buffer_original = batch.metadata_buffer;
|
|
481
|
+
|
|
482
|
+
this.#records.push(record);
|
|
483
|
+
|
|
484
|
+
return record;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Release a batch allocation back to the data and metadata allocators. The GPU bytes are
|
|
489
|
+
* not cleared — the freed slices are reclaimed lazily by the next {@link compact} (a
|
|
490
|
+
* deallocation bumps the compaction counter the allocator consults under pressure).
|
|
491
|
+
* Other batches' allocations are unaffected (the OffsetAllocator frees disjoint slices),
|
|
492
|
+
* so callers only need to ensure nothing still references this batch's metadata rows
|
|
493
|
+
* (the geometry table rebuild in {@link GPUGeometryManager} handles that).
|
|
494
|
+
*
|
|
495
|
+
* @param {MeshletBatchAllocationRecord} record a record returned by {@link add_batch} or
|
|
496
|
+
* {@link clone_batch_allocation}
|
|
497
|
+
* @returns {boolean} true if the record was owned and freed
|
|
498
|
+
*/
|
|
499
|
+
remove_batch(record) {
|
|
500
|
+
assert.defined(record, 'record');
|
|
501
|
+
|
|
502
|
+
const index = this.#records.indexOf(record);
|
|
503
|
+
if (index === -1) {
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
this.#allocator_data.free(record.data);
|
|
508
|
+
this.#allocator_metadata.free(record.metadata);
|
|
509
|
+
|
|
510
|
+
this.#records.splice(index, 1);
|
|
511
|
+
this.#deallocations_since_last_rebuild++;
|
|
512
|
+
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Allocate a fresh (data, metadata) pair sized to mirror `source`,
|
|
518
|
+
* and queue a GPU-side clone: the source's data and metadata are
|
|
519
|
+
* copied into the new ranges via `copyBufferToBuffer`, then a
|
|
520
|
+
* compute pass patches the cloned metadata records' `address`
|
|
521
|
+
* fields to point at the new data range. Both the copies and the
|
|
522
|
+
* patch dispatch land when the host next calls
|
|
523
|
+
* {@link update update(cmd_ctx)}.
|
|
524
|
+
*
|
|
525
|
+
* The returned record can be wired into the geometry table
|
|
526
|
+
* immediately — its `data.offset` and `metadata.offset` are valid
|
|
527
|
+
* the moment this call returns. The GPU bytes at those addresses
|
|
528
|
+
* just aren't populated yet; downstream passes that consume the
|
|
529
|
+
* clone must run after the next `update`. Those addresses may still
|
|
530
|
+
* move before the flush, which is why nothing outside the record is
|
|
531
|
+
* allowed to remember them.
|
|
532
|
+
*
|
|
533
|
+
* Sharing the source's `metadata_buffer_original` lets a future
|
|
534
|
+
* compaction patch the clone's metadata from the same un-patched
|
|
535
|
+
* CPU bytes the source uses — the post-patch state on the GPU is
|
|
536
|
+
* identical to the source aside from the data offset.
|
|
537
|
+
*
|
|
538
|
+
* @param {MeshletBatchAllocationRecord} source
|
|
539
|
+
* @returns {MeshletBatchAllocationRecord}
|
|
540
|
+
*/
|
|
541
|
+
clone_batch_allocation(source) {
|
|
542
|
+
assert.defined(source, 'source');
|
|
543
|
+
assert.greaterThan(source.meshlet_count, 0, 'source.meshlet_count');
|
|
544
|
+
|
|
545
|
+
const { data, metadata } = this.#allocate_data_and_metadata(source.data_size, source.meshlet_count);
|
|
546
|
+
|
|
547
|
+
const record = new MeshletBatchAllocationRecord();
|
|
548
|
+
|
|
549
|
+
record.data = data;
|
|
550
|
+
record.metadata = metadata;
|
|
551
|
+
|
|
552
|
+
record.meshlet_count = source.meshlet_count;
|
|
553
|
+
record.data_size = source.data_size;
|
|
554
|
+
|
|
555
|
+
// Share the un-patched CPU bytes so a future compact rewrites
|
|
556
|
+
// the clone's metadata correctly under its new data offset.
|
|
557
|
+
record.metadata_buffer_original = source.metadata_buffer_original;
|
|
558
|
+
|
|
559
|
+
this.#records.push(record);
|
|
560
|
+
|
|
561
|
+
// The queue names the two records rather than the addresses they
|
|
562
|
+
// hold right now. Both are in `#records`, so a rebuild between
|
|
563
|
+
// this call and the flush moves them and the flush still reads
|
|
564
|
+
// where they went — which is what lets a clone be queued in the
|
|
565
|
+
// same frame as the growth another geometry's arrival forces.
|
|
566
|
+
this.#pending_clones.push({ source, clone: record });
|
|
567
|
+
|
|
568
|
+
return record;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Flush any pending clone work into `cmd_ctx`. For each queued
|
|
573
|
+
* clone, emits two `copyBufferToBuffer` commands (one for vertex
|
|
574
|
+
* data, one for metadata records). After every queued clone's
|
|
575
|
+
* copies are recorded, dispatches a single batched patch shader
|
|
576
|
+
* pass that walks a flat `(record_index, address_delta)` table
|
|
577
|
+
* — N clones → 1 patch dispatch, total threads = sum of clone
|
|
578
|
+
* meshlet counts.
|
|
579
|
+
*
|
|
580
|
+
* Idempotent and cheap when nothing's queued.
|
|
581
|
+
*
|
|
582
|
+
* @param {ShadeGPUCommandContext} cmd_ctx
|
|
583
|
+
*/
|
|
584
|
+
update(cmd_ctx) {
|
|
585
|
+
const pending = this.#pending_clones;
|
|
586
|
+
if (pending.length === 0) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
const data_buffer = this.#meshlet_data_buffer;
|
|
591
|
+
const metadata_buffer = this.#meshlet_metadata_buffer;
|
|
592
|
+
const metadata_stride = MESHLET_METADATA_STRUCT.aligned_size;
|
|
593
|
+
const metadata_stride_words = metadata_stride / 4;
|
|
594
|
+
|
|
595
|
+
// WebGPU forbids `copyBufferToBuffer` with src === dst even when
|
|
596
|
+
// ranges don't overlap (the validation check is buffer-identity,
|
|
597
|
+
// not range-overlap), so we relocate via a small compute-shader
|
|
598
|
+
// memcpy bound to the buffer once as `read_write`. Two dispatches
|
|
599
|
+
// — one over the data-buffer regions, one over the metadata-buffer
|
|
600
|
+
// regions — handle every queued clone in a batched pass.
|
|
601
|
+
//
|
|
602
|
+
// Region (src, dst) ranges are non-overlapping by construction:
|
|
603
|
+
// the OffsetAllocator hands out fresh disjoint slices, so the
|
|
604
|
+
// memcpy shader can safely skip the per-thread overlap check.
|
|
605
|
+
const region_size_bytes = BUFFER_INTRA_COPY_REGION_STRUCT.aligned_size;
|
|
606
|
+
|
|
607
|
+
const data_regions_array = new Uint32Array(pending.length * (region_size_bytes / 4));
|
|
608
|
+
const metadata_regions_array = new Uint32Array(pending.length * (region_size_bytes / 4));
|
|
609
|
+
|
|
610
|
+
let total_records = 0;
|
|
611
|
+
for (let i = 0; i < pending.length; i++) {
|
|
612
|
+
const { source, clone } = pending[i];
|
|
613
|
+
|
|
614
|
+
// Region struct is just three u32s — write directly. Order
|
|
615
|
+
// matches the field declaration: src_offset, dst_offset,
|
|
616
|
+
// word_count.
|
|
617
|
+
const region_words = i * 3;
|
|
618
|
+
data_regions_array[region_words] = source.data.offset;
|
|
619
|
+
data_regions_array[region_words + 1] = clone.data.offset;
|
|
620
|
+
data_regions_array[region_words + 2] = clone.data_size;
|
|
621
|
+
|
|
622
|
+
metadata_regions_array[region_words] = source.metadata.offset * metadata_stride_words;
|
|
623
|
+
metadata_regions_array[region_words + 1] = clone.metadata.offset * metadata_stride_words;
|
|
624
|
+
metadata_regions_array[region_words + 2] = clone.meshlet_count * metadata_stride_words;
|
|
625
|
+
|
|
626
|
+
total_records += clone.meshlet_count;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
const data_regions_buffer = cmd_ctx.allocateTransientBufferAndLoad(
|
|
630
|
+
data_regions_array.buffer,
|
|
631
|
+
GPUBufferUsage.STORAGE,
|
|
632
|
+
);
|
|
633
|
+
shader_buffer_intra_copy_regions.dispatch({
|
|
634
|
+
encoder: cmd_ctx,
|
|
635
|
+
group_count_x: pending.length,
|
|
636
|
+
bindings: {
|
|
637
|
+
buffer: data_buffer,
|
|
638
|
+
regions: data_regions_buffer,
|
|
639
|
+
},
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
const metadata_regions_buffer = cmd_ctx.allocateTransientBufferAndLoad(
|
|
643
|
+
metadata_regions_array.buffer,
|
|
644
|
+
GPUBufferUsage.STORAGE,
|
|
645
|
+
);
|
|
646
|
+
shader_buffer_intra_copy_regions.dispatch({
|
|
647
|
+
encoder: cmd_ctx,
|
|
648
|
+
group_count_x: pending.length,
|
|
649
|
+
bindings: {
|
|
650
|
+
buffer: metadata_buffer,
|
|
651
|
+
regions: metadata_regions_buffer,
|
|
652
|
+
},
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
// Build the flat (record_index, address_delta) table. One pair
|
|
656
|
+
// per cloned meshlet record. Uploaded as a transient storage
|
|
657
|
+
// buffer the patch shader binds for one dispatch.
|
|
658
|
+
const patches_array = new Uint32Array(total_records * 2);
|
|
659
|
+
let p = 0;
|
|
660
|
+
for (let i = 0; i < pending.length; i++) {
|
|
661
|
+
const { source, clone } = pending[i];
|
|
662
|
+
|
|
663
|
+
// Address delta is in u32 word units. When the clone's offset
|
|
664
|
+
// is below the source's, the unsigned subtraction wraps — the
|
|
665
|
+
// patch shader does the matching wrapping add, so the final
|
|
666
|
+
// per-record `address` lands at the right absolute word offset
|
|
667
|
+
// either way.
|
|
668
|
+
const address_delta = (clone.data.offset - source.data.offset) >>> 0;
|
|
669
|
+
|
|
670
|
+
for (let m = 0; m < clone.meshlet_count; m++) {
|
|
671
|
+
patches_array[p++] = clone.metadata.offset + m;
|
|
672
|
+
patches_array[p++] = address_delta;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
const patches_buffer = cmd_ctx.allocateTransientBufferAndLoad(
|
|
677
|
+
patches_array.buffer,
|
|
678
|
+
GPUBufferUsage.STORAGE,
|
|
679
|
+
);
|
|
680
|
+
|
|
681
|
+
shader_meshlet_metadata_address_patch.dispatchThreads({
|
|
682
|
+
encoder: cmd_ctx,
|
|
683
|
+
thread_count_x: total_records,
|
|
684
|
+
bindings: {
|
|
685
|
+
meshlet_metadata: metadata_buffer,
|
|
686
|
+
patches: patches_buffer,
|
|
687
|
+
patch_count: total_records,
|
|
688
|
+
},
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
pending.length = 0;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
destroy() {
|
|
695
|
+
this.#meshlet_data_buffer.destroy();
|
|
696
|
+
this.#meshlet_metadata_buffer.destroy();
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
*
|
|
701
|
+
* @param {MeshletBatch} batch
|
|
702
|
+
* @returns {MeshletBatchAllocationRecord}
|
|
703
|
+
*/
|
|
704
|
+
add_batch(batch) {
|
|
705
|
+
assert.defined(batch, 'batch');
|
|
706
|
+
assert.notNull(batch, 'batch');
|
|
707
|
+
assert.equal(batch.isMeshletBatch, true, 'batch.isMeshletBatch !== true');
|
|
708
|
+
|
|
709
|
+
const record = this.#allocate_for_batch(batch);
|
|
710
|
+
|
|
711
|
+
// plonk data
|
|
712
|
+
const data_buffer = batch.data_buffer;
|
|
713
|
+
const data_allocation = record.data;
|
|
714
|
+
|
|
715
|
+
this.#device.queue.writeBuffer(
|
|
716
|
+
this.#meshlet_data_buffer,
|
|
717
|
+
data_allocation.offset << 2, // allocator works in words of 4 bytes
|
|
718
|
+
data_buffer
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
// Write Metadata (Patch & Upload)
|
|
722
|
+
this.#write_patched_metadata(
|
|
723
|
+
record.metadata_buffer_original,
|
|
724
|
+
record.meshlet_count,
|
|
725
|
+
record.data.offset,
|
|
726
|
+
record.metadata.offset,
|
|
727
|
+
this.#meshlet_metadata_buffer
|
|
728
|
+
);
|
|
729
|
+
|
|
730
|
+
return record;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
async debug_dump_metadata() {
|
|
734
|
+
const device = this.#device;
|
|
735
|
+
|
|
736
|
+
return await inspect_gpu_buffer_typed({
|
|
737
|
+
buffer: this.#meshlet_metadata_buffer,
|
|
738
|
+
device,
|
|
739
|
+
type: MESHLET_METADATA_STRUCT,
|
|
740
|
+
count: Math.floor(this.#meshlet_metadata_buffer.size / MESHLET_METADATA_STRUCT.aligned_size),
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
get gpu_memory_usage_occupied() {
|
|
745
|
+
let result = 0;
|
|
746
|
+
|
|
747
|
+
for (const record of this.#records) {
|
|
748
|
+
result += record.data_size * 4;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
return result;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
get gpu_memory_usage() {
|
|
755
|
+
let result = 0;
|
|
756
|
+
|
|
757
|
+
if (this.#meshlet_data_buffer) {
|
|
758
|
+
result += this.#meshlet_data_buffer.size;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
if (this.#meshlet_metadata_buffer) {
|
|
762
|
+
result += this.#meshlet_metadata_buffer.size;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return result;
|
|
766
|
+
}
|
|
775
767
|
}
|