@woosh/meep-engine 3.59.0 → 3.60.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/shade/playground/probe_clipmap/index.html +12 -0
- package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
- package/src/shade/playground/probe_clipmap/main.js +5 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +4 -6
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +63 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +228 -16
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +27 -4
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +526 -23
- package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.d.ts +11 -0
- package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.d.ts.map +1 -0
- package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.js +21 -0
- package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.d.ts +65 -0
- package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.d.ts.map +1 -0
- package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.js +376 -0
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.d.ts +7 -3
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.js +70 -6
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.d.ts +20 -0
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.d.ts.map +1 -0
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.js +80 -0
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.d.ts +18 -0
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.d.ts.map +1 -0
- package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.js +113 -0
- package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts +47 -0
- package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.js +80 -0
- package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts +91 -0
- package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.js +902 -0
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts +16 -0
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.js +67 -0
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.js +145 -0
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts +12 -0
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.js +105 -0
- package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.js +2 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +3 -9
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +13 -31
- package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +764 -48
- package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +410 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +3 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +4 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +41 -17
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +57 -33
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts +11 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.js +13 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +9 -18
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +8 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.d.ts +12 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.js +28 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +1 -29
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +1 -74
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.d.ts +161 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.js +219 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts +1 -8
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.js +1 -9
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.d.ts +40 -12
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.js +373 -31
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts +2 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js +2 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.d.ts +15 -8
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.js +28 -14
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.d.ts +23 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.js +66 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.d.ts +29 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.js +210 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.d.ts +29 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.js +86 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.d.ts +41 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.js +439 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.d.ts +23 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.js +135 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.d.ts +3 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.js +12 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +21 -18
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +254 -73
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +149 -8
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +181 -13
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +179 -7
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +412 -31
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +4 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +4 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +36 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +218 -29
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts +5 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +24 -14
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +15 -6
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +21 -22
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.d.ts +36 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.js +257 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts +18 -7
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +157 -51
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.d.ts +23 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.js +110 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +24 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +90 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts +45 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.js +205 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts +16 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +55 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +19 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +60 -6
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts +10 -9
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +32 -39
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts +21 -14
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +100 -30
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts +6 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.js +26 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts +3 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.js +12 -12
- package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.d.ts +10 -0
- package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.js +21 -0
- package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts +5 -2
- package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.js +31 -23
- package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.d.ts +10 -0
- package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.js +22 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.d.ts +9 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.js +18 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts +8 -3
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.js +41 -32
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.d.ts +31 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.js +71 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.d.ts +47 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.js +210 -0
- package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +5 -4
- package/src/shade/renderer/gpu_primitive/sort/defs.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/defs.js +5 -4
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +56 -15
- 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 +410 -61
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts +4 -1
- 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 +16 -42
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.d.ts +15 -0
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.js +60 -0
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.d.ts +25 -0
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.js +89 -0
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts +3 -8
- 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 +28 -160
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.d.ts +12 -0
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.js +74 -0
- package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts +3 -1
- package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.js +387 -188
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.js +1 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.js +1 -1
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +90 -72
- package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.d.ts +5 -0
- package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.d.ts.map +1 -1
- package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.js +9 -0
- package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.d.ts +13 -0
- package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.d.ts.map +1 -0
- package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.js +14 -0
- package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.d.ts +10 -0
- package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.d.ts.map +1 -0
- package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.js +15 -0
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.d.ts +4 -3
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.js +6 -5
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.d.ts +17 -2
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.js +25 -57
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.d.ts +13 -0
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.d.ts.map +1 -0
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.js +70 -0
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.d.ts +10 -0
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.d.ts.map +1 -0
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.js +59 -0
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.d.ts +12 -0
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.d.ts.map +1 -0
- package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.js +49 -0
- package/src/shade/renderer/path_tracer/shader/chunk_ray_hit_to_opacity.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/shader/chunk_ray_hit_to_opacity.js +1 -0
- package/src/shade/renderer/path_tracer/shader/chunk_render_trace_path.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/shader/chunk_render_trace_path.js +1 -0
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material.js +2 -1
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts +7 -0
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +15 -6
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +7 -1
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +26 -1
- package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.d.ts +7 -7
- package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.js +262 -294
- package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.d.ts +9 -0
- package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.js +21 -0
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +43 -0
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +87 -0
- package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.d.ts +7 -1
- package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.js +1 -1
- package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.d.ts +21 -0
- package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.js +42 -0
- package/src/shade/renderer/wind/GPUSceneWind.d.ts +1 -1
- package/src/shade/wgsl/emulator/CPUBitmapData.d.ts +19 -0
- package/src/shade/wgsl/emulator/CPUBitmapData.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/CPUBitmapData.js +27 -0
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +65 -19
- package/src/view/elements/progress/segmented/GhostTrail.d.ts +116 -0
- package/src/view/elements/progress/segmented/GhostTrail.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/GhostTrail.js +280 -0
- package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.d.ts +3 -1
- package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.d.ts.map +1 -1
- package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.js +3 -1
- package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.d.ts +11 -0
- package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.js +15 -0
- package/src/view/elements/progress/segmented/SegmentDefinition.d.ts +3 -0
- package/src/view/elements/progress/segmented/SegmentDefinition.d.ts.map +1 -1
- package/src/view/elements/progress/segmented/SegmentDefinition.js +3 -0
- package/src/view/elements/progress/segmented/SegmentTier.d.ts +38 -0
- package/src/view/elements/progress/segmented/SegmentTier.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/SegmentTier.js +50 -0
- package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts +163 -10
- package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts.map +1 -1
- package/src/view/elements/progress/segmented/SegmentedResourceBarView.js +442 -101
- package/src/view/elements/progress/segmented/playground/index.html +78 -0
- package/src/view/elements/progress/segmented/playground/main.d.ts +2 -0
- package/src/view/elements/progress/segmented/playground/main.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/playground/main.js +173 -0
- package/src/view/elements/progress/segmented/segment_cell_layout.d.ts +48 -0
- package/src/view/elements/progress/segmented/segment_cell_layout.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/segment_cell_layout.js +75 -0
- package/src/view/elements/progress/segmented/segment_notch_place.d.ts +18 -0
- package/src/view/elements/progress/segmented/segment_notch_place.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/segment_notch_place.js +28 -0
- package/src/view/elements/progress/segmented/segment_tick_positions.d.ts +32 -0
- package/src/view/elements/progress/segmented/segment_tick_positions.d.ts.map +1 -0
- package/src/view/elements/progress/segmented/segment_tick_positions.js +103 -0
- package/src/view/elements/progress/segmented/segmented-resource-bar.css +142 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.d.ts +0 -35
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.js +0 -238
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts +0 -99
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.js +0 -139
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts +0 -65
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.js +0 -393
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts +0 -17
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.js +0 -36
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts +0 -29
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.js +0 -108
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts +0 -31
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.js +0 -113
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts +0 -36
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.js +0 -85
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts +0 -23
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.js +0 -273
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts +0 -13
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.js +0 -151
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts +0 -13
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.js +0 -133
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts +0 -22
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.js +0 -135
|
@@ -0,0 +1,902 @@
|
|
|
1
|
+
import { assert } from "../../../../../core/assert.js";
|
|
2
|
+
import { BufferDescriptor } from "../../../../descriptor/buffer/BufferDescriptor.js";
|
|
3
|
+
import { BufferResourceDescriptor } from "../../../../device/graph/BufferResourceDescriptor.js";
|
|
4
|
+
import { graph_read_buffer } from "../../../buffer/graph_read_buffer.js";
|
|
5
|
+
import { graph_build_indirect_dispatch_command } from "../../../gpu_primitive/indirect/IndirectComputeCommandBuildPass.js";
|
|
6
|
+
import {
|
|
7
|
+
graph_prefix_scan_csdldf,
|
|
8
|
+
prefix_scan_csdldf_output_descriptor
|
|
9
|
+
} from "../../../gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js";
|
|
10
|
+
import { graph_create_buffer } from "../../../shader/graph/graph_create_buffer.js";
|
|
11
|
+
import { Attribute } from "../../Attribute.js";
|
|
12
|
+
import { Geometry } from "../../Geometry.js";
|
|
13
|
+
import { MeshoptClusterizer } from "../../meshlet/build/meshoptimizer/meshopt_clusterizer.js";
|
|
14
|
+
import { meshlet_geometry_build_from_geometry } from "../../meshlet_geometry_build_from_geometry.js";
|
|
15
|
+
import { MeshSDFState } from "../../sdf/MESH_SDF.js";
|
|
16
|
+
import { MeshSDFLayout } from "../../sdf/MeshSDFLayout.js";
|
|
17
|
+
import { StandardAttributes } from "../../StandardAttributes.js";
|
|
18
|
+
import { vgeo_feedback_slot_stats } from "../runtime/cut/vgeo_cut_feedback_layout.js";
|
|
19
|
+
import { graph_vgeo_cut_descent } from "../runtime/graph_vgeo_cut_descent.js";
|
|
20
|
+
import { VGEO_CUT_STAT } from "../runtime/layout/VGEO_CUT_STAT.js";
|
|
21
|
+
import { VGEO_CUT_STAT_COUNT } from "../runtime/layout/VGEO_CUT_STAT_COUNT.js";
|
|
22
|
+
import { VGEO_GEOMETRY_ROW_NONE } from "../runtime/layout/VGEO_GEOMETRY_ROW_NONE.js";
|
|
23
|
+
import { VGEO_INSTANCE_WORDS } from "../runtime/layout/VGEO_INSTANCE_WORDS.js";
|
|
24
|
+
import { VGeoViewCut } from "../runtime/VGeoViewCut.js";
|
|
25
|
+
import { shader_vgeo_sdf_collect, VGEO_SDF_COLLECT_WORKGROUP_SIZE } from "./shader_vgeo_sdf_collect.js";
|
|
26
|
+
import { shader_vgeo_sdf_decode } from "./shader_vgeo_sdf_decode.js";
|
|
27
|
+
import { shader_vgeo_sdf_traverse } from "./shader_vgeo_sdf_traverse.js";
|
|
28
|
+
import {
|
|
29
|
+
VGEO_SDF_CLUSTER_WORDS,
|
|
30
|
+
VGEO_SDF_COUNTER,
|
|
31
|
+
VGEO_SDF_COUNTER_WORDS,
|
|
32
|
+
VGEO_SDF_JOB_STRUCT,
|
|
33
|
+
vgeo_sdf_header_words
|
|
34
|
+
} from "./VGEO_SDF.js";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
|
|
38
|
+
* @typedef {import("../../GPUGeometryManager.js").GPUGeometryManager} GPUGeometryManager
|
|
39
|
+
* @typedef {import("../../GPUGeometryMetadata.js").GPUGeometryMetadata} GPUGeometryMetadata
|
|
40
|
+
* @typedef {import("../../MeshletGeometry.js").MeshletGeometry} MeshletGeometry
|
|
41
|
+
* @typedef {import("../runtime/GPUVirtualGeometryRuntime.js").GPUVirtualGeometryRuntime} GPUVirtualGeometryRuntime
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/** The slot holds no geometry. */
|
|
45
|
+
const JOB_FREE = 0;
|
|
46
|
+
/** Cut each frame, its counters read back. */
|
|
47
|
+
const JOB_CUT = 1;
|
|
48
|
+
/** Its last cut read back stood nothing in: the next frame it is cut, its mesh is written out too. */
|
|
49
|
+
const JOB_READY = 2;
|
|
50
|
+
/** Written out in a frame whose readback has not landed. */
|
|
51
|
+
const JOB_DECODING = 3;
|
|
52
|
+
/** Its mesh is read back: its proxy is built on the host. */
|
|
53
|
+
const JOB_BUILD = 4;
|
|
54
|
+
/** Its proxy is baked by the mesh path. */
|
|
55
|
+
const JOB_BAKING = 5;
|
|
56
|
+
/** Its proxy's cache is resident: given to the geometry at the next update. */
|
|
57
|
+
const JOB_BAKED = 6;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Frames whose readback may be in flight before a frame's cut is skipped, as the bake's log: a mapping lands a frame or
|
|
61
|
+
* two after its copy, and past this the device is behind.
|
|
62
|
+
* @type {number}
|
|
63
|
+
*/
|
|
64
|
+
const MAX_FRAMES_IN_FLIGHT = 3;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Geometries extracted at once: the jobs cut each frame until their cut stands nothing in. One whose proxy is built,
|
|
68
|
+
* baking or waiting to be given its cache keeps its slot until then.
|
|
69
|
+
* @type {number}
|
|
70
|
+
*/
|
|
71
|
+
const DEFAULT_JOB_CAPACITY = 32;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Entries the cluster list starts with: a cut of a typical geometry at half its cache's voxel is under 128 clusters
|
|
75
|
+
* (S8, step 0), for each of {@link DEFAULT_JOB_CAPACITY} jobs. It doubles past what a frame's cut took.
|
|
76
|
+
* @type {number}
|
|
77
|
+
*/
|
|
78
|
+
const INITIAL_CLUSTER_CAPACITY = DEFAULT_JOB_CAPACITY * 128;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* One geometry being extracted.
|
|
82
|
+
*/
|
|
83
|
+
class VGeoSDFJob {
|
|
84
|
+
/**
|
|
85
|
+
* Bumped each time the slot takes a geometry: a readback of a frame cut for an earlier one is not this one's.
|
|
86
|
+
* @type {number}
|
|
87
|
+
*/
|
|
88
|
+
generation = 0;
|
|
89
|
+
|
|
90
|
+
phase = JOB_FREE;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The geometry, whose cache is asked for.
|
|
94
|
+
* @type {GPUGeometryMetadata|null}
|
|
95
|
+
*/
|
|
96
|
+
record = null;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* What puts its error against a τ of 1: one over half its cache's level-0 voxel, in its own units.
|
|
100
|
+
* @type {number}
|
|
101
|
+
*/
|
|
102
|
+
projection_k = 0;
|
|
103
|
+
|
|
104
|
+
/** What its last complete cut held. */
|
|
105
|
+
vertex_count = 0;
|
|
106
|
+
triangle_count = 0;
|
|
107
|
+
|
|
108
|
+
/** @type {Float32Array|null} */
|
|
109
|
+
positions = null;
|
|
110
|
+
|
|
111
|
+
/** @type {Uint32Array|null} */
|
|
112
|
+
indices = null;
|
|
113
|
+
|
|
114
|
+
/** @type {MeshletGeometry|null} */
|
|
115
|
+
proxy = null;
|
|
116
|
+
|
|
117
|
+
/** @type {GPUGeometryMetadata|null} */
|
|
118
|
+
proxy_record = null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The jobs one recorded frame cut, for its readback.
|
|
123
|
+
*/
|
|
124
|
+
class VGeoSDFFrame {
|
|
125
|
+
busy = false;
|
|
126
|
+
|
|
127
|
+
count = 0;
|
|
128
|
+
|
|
129
|
+
/** @type {VGeoSDFJob[]} */
|
|
130
|
+
jobs = [];
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param {number} capacity
|
|
134
|
+
*/
|
|
135
|
+
constructor(capacity) {
|
|
136
|
+
this.generations = new Uint32Array(capacity);
|
|
137
|
+
this.decoding = new Uint8Array(capacity);
|
|
138
|
+
this.vertex_bases = new Uint32Array(capacity);
|
|
139
|
+
this.triangle_bases = new Uint32Array(capacity);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
vertex_offset = 0;
|
|
143
|
+
index_offset = 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The geometry caches of virtual geometry (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §7.8, as S8 built it): a
|
|
148
|
+
* {@link MeshSDFSource} of {@link GPUGeometrySDFManager}, which bakes a geometry's field from its tree, and a virtual
|
|
149
|
+
* geometry has none. Each virtual geometry whose cache is asked for gets a proxy, the triangles of a cut of it, baked by
|
|
150
|
+
* the mesh path as any geometry is, and its resident cache adopted into the geometry. Its instances are then composed
|
|
151
|
+
* from it as a mesh's are.
|
|
152
|
+
*
|
|
153
|
+
* **The cut.** A geometry is cut whole by the camera cut's own descent (`shader_vgeo_sdf_traverse`), at an error under
|
|
154
|
+
* half its cache's level-0 voxel, in its own space, under a feedback slot of the extraction's own: a cluster's page not
|
|
155
|
+
* resident is wanted there, as a view's are, and since a want lasts one reading the job is cut again each frame until
|
|
156
|
+
* its cut stands nothing in. Its counters are read back each frame.
|
|
157
|
+
*
|
|
158
|
+
* **The mesh.** The frame after a cut that stood nothing in, the job's clusters are written out too, its vertices as
|
|
159
|
+
* stored and its triangles as indices into them (`shader_vgeo_sdf_decode`), in room the last cut's counts made, and
|
|
160
|
+
* read back with that frame's counters. A frame that cut it otherwise (a page evicted since, the cut grown) is not
|
|
161
|
+
* taken, and the job is cut again.
|
|
162
|
+
*
|
|
163
|
+
* **The proxy.** One a frame, on the host: an ordinary geometry built from the mesh
|
|
164
|
+
* (`meshlet_geometry_build_from_geometry`, which costs 2.2 to 4.1 µs a triangle, measured), added to the geometry
|
|
165
|
+
* manager, its cache held with the side the geometry's holders draw. When its bake turns resident the next update gives
|
|
166
|
+
* it to the geometry ({@link GPUGeometrySDFManager#adopt}) and removes the proxy.
|
|
167
|
+
*
|
|
168
|
+
* A geometry no longer asked for when its turn comes is let go, and one whose holders ask again is extracted again.
|
|
169
|
+
* Settings that change the caches' voxel restart every job.
|
|
170
|
+
*/
|
|
171
|
+
export class VGeoSDFProxies {
|
|
172
|
+
|
|
173
|
+
/** @type {GPUDevice} */
|
|
174
|
+
#device;
|
|
175
|
+
|
|
176
|
+
/** @type {GPUVirtualGeometryRuntime} */
|
|
177
|
+
#runtime;
|
|
178
|
+
|
|
179
|
+
/** @type {GPUGeometryManager} */
|
|
180
|
+
#geometries;
|
|
181
|
+
|
|
182
|
+
/** @type {import("../../sdf/GPUGeometrySDFManager.js").GPUGeometrySDFManager} */
|
|
183
|
+
#sdf;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The extraction's cut: its slot, its params and its wavefront bound.
|
|
187
|
+
* @type {VGeoViewCut}
|
|
188
|
+
*/
|
|
189
|
+
#cut;
|
|
190
|
+
|
|
191
|
+
/** @type {VGeoSDFJob[]} */
|
|
192
|
+
#jobs = [];
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Geometries asked for and not yet a job's, in the order asked; a geometry asked for again or let go since may be
|
|
196
|
+
* here, and is passed over.
|
|
197
|
+
* @type {GPUGeometryMetadata[]}
|
|
198
|
+
*/
|
|
199
|
+
#requested = [];
|
|
200
|
+
|
|
201
|
+
/** @type {VGeoSDFFrame[]} */
|
|
202
|
+
#frames = [];
|
|
203
|
+
|
|
204
|
+
#cluster_capacity = INITIAL_CLUSTER_CAPACITY;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* The frame's jobs as the passes read them, `VGEO_SDF_JOB_STRUCT` each.
|
|
208
|
+
* @type {GPUBuffer}
|
|
209
|
+
*/
|
|
210
|
+
#jobs_buffer;
|
|
211
|
+
|
|
212
|
+
#jobs_scratch;
|
|
213
|
+
|
|
214
|
+
#settings = { job_count: 0, cluster_capacity: 0, vertex_offset: 0, index_offset: 0 };
|
|
215
|
+
|
|
216
|
+
#collect_data = { instances: -1, claim_widths: -1 };
|
|
217
|
+
#collect_bindings = {};
|
|
218
|
+
#decode_data = { command: -1, clusters: -1, counters: -1, payload: -1 };
|
|
219
|
+
#decode_bindings = {};
|
|
220
|
+
#header_data = { counters: -1, feedback: -1, payload: -1 };
|
|
221
|
+
|
|
222
|
+
/** Where the extraction's slot keeps its counters in the frame's feedback, for the frame being recorded. */
|
|
223
|
+
#stats_base = 0;
|
|
224
|
+
|
|
225
|
+
#voxel_size;
|
|
226
|
+
#max_bricks;
|
|
227
|
+
|
|
228
|
+
#layout = new MeshSDFLayout();
|
|
229
|
+
|
|
230
|
+
#clusterizer_ready = false;
|
|
231
|
+
|
|
232
|
+
#extracted_count = 0;
|
|
233
|
+
#adopted_count = 0;
|
|
234
|
+
#triangles_extracted = 0;
|
|
235
|
+
|
|
236
|
+
#destroyed = false;
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* @param {Object} options
|
|
240
|
+
* @param {GPUDevice} options.device
|
|
241
|
+
* @param {GPUVirtualGeometryRuntime} options.runtime whose geometries' caches this makes
|
|
242
|
+
* @param {GPUGeometryManager} options.geometries the scene's, whose caches the virtual geometries' are
|
|
243
|
+
* @param {number} [options.job_capacity] geometries extracted at once
|
|
244
|
+
*/
|
|
245
|
+
constructor({ device, runtime, geometries, job_capacity = DEFAULT_JOB_CAPACITY }) {
|
|
246
|
+
assert.defined(device, 'device');
|
|
247
|
+
assert.defined(runtime, 'runtime');
|
|
248
|
+
assert.defined(geometries, 'geometries');
|
|
249
|
+
assert.isPositiveInteger(job_capacity, 'job_capacity');
|
|
250
|
+
|
|
251
|
+
this.#device = device;
|
|
252
|
+
this.#runtime = runtime;
|
|
253
|
+
this.#geometries = geometries;
|
|
254
|
+
this.#sdf = geometries.sdf;
|
|
255
|
+
this.#cut = new VGeoViewCut({ device, label: 'vgeo sdf proxies' });
|
|
256
|
+
|
|
257
|
+
this.#voxel_size = this.#sdf.voxel_size;
|
|
258
|
+
this.#max_bricks = this.#sdf.max_bricks;
|
|
259
|
+
|
|
260
|
+
for (let i = 0; i < job_capacity; i++) {
|
|
261
|
+
this.#jobs.push(new VGeoSDFJob());
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
for (let i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
|
265
|
+
this.#frames.push(new VGeoSDFFrame(job_capacity));
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
this.#jobs_buffer = device.createBuffer(BufferDescriptor.fromJSON({
|
|
269
|
+
label: 'VGeoSDFProxies/jobs',
|
|
270
|
+
size: job_capacity * VGEO_SDF_JOB_STRUCT.size,
|
|
271
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
272
|
+
}));
|
|
273
|
+
|
|
274
|
+
this.#jobs_scratch = new DataView(new ArrayBuffer(job_capacity * VGEO_SDF_JOB_STRUCT.size));
|
|
275
|
+
|
|
276
|
+
const ready = MeshoptClusterizer.ready;
|
|
277
|
+
|
|
278
|
+
if (ready === undefined) {
|
|
279
|
+
this.#clusterizer_ready = true;
|
|
280
|
+
} else {
|
|
281
|
+
ready.then(() => {
|
|
282
|
+
this.#clusterizer_ready = true;
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
this.#sdf.onRequested.add(this.#requested_one, this);
|
|
287
|
+
this.#sdf.onBaked.add(this.#baked, this);
|
|
288
|
+
this.#sdf.add_source(this);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* The extraction's cut, whose `stats` say what the last reading of its slot counted.
|
|
293
|
+
* @returns {VGeoViewCut}
|
|
294
|
+
*/
|
|
295
|
+
get cut() {
|
|
296
|
+
return this.#cut;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Geometries being extracted.
|
|
301
|
+
* @returns {number}
|
|
302
|
+
*/
|
|
303
|
+
get job_count() {
|
|
304
|
+
let count = 0;
|
|
305
|
+
|
|
306
|
+
for (const job of this.#jobs) {
|
|
307
|
+
if (job.phase !== JOB_FREE) {
|
|
308
|
+
count++;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return count;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Geometries asked for that wait for a job, those let go since included.
|
|
317
|
+
* @returns {number}
|
|
318
|
+
*/
|
|
319
|
+
get requested_count() {
|
|
320
|
+
return this.#requested.length;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Proxies built so far.
|
|
325
|
+
* @returns {number}
|
|
326
|
+
*/
|
|
327
|
+
get extracted_count() {
|
|
328
|
+
return this.#extracted_count;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Caches given to their geometries so far.
|
|
333
|
+
* @returns {number}
|
|
334
|
+
*/
|
|
335
|
+
get adopted_count() {
|
|
336
|
+
return this.#adopted_count;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Triangles of the proxies built so far.
|
|
341
|
+
* @returns {number}
|
|
342
|
+
*/
|
|
343
|
+
get triangles_extracted() {
|
|
344
|
+
return this.#triangles_extracted;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Entries the cluster list holds.
|
|
349
|
+
* @returns {number}
|
|
350
|
+
*/
|
|
351
|
+
get cluster_capacity() {
|
|
352
|
+
return this.#cluster_capacity;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* @param {GPUGeometryMetadata} record
|
|
357
|
+
*/
|
|
358
|
+
#requested_one(record) {
|
|
359
|
+
if (record.vg_row !== VGEO_GEOMETRY_ROW_NONE) {
|
|
360
|
+
this.#requested.push(record);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* @param {number} id
|
|
366
|
+
*/
|
|
367
|
+
#baked(id) {
|
|
368
|
+
for (const job of this.#jobs) {
|
|
369
|
+
if (job.phase === JOB_BAKING && job.proxy_record.index === id) {
|
|
370
|
+
job.phase = JOB_BAKED;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* The frame's work, ahead of the caches' bake: the caches baked given to their geometries, a proxy built, jobs
|
|
377
|
+
* started, and the jobs' cut recorded into `graph` while the runtime's frame is open.
|
|
378
|
+
*
|
|
379
|
+
* @param {FrameGraph} graph
|
|
380
|
+
*/
|
|
381
|
+
graph_update(graph) {
|
|
382
|
+
assert.notOk(this.#destroyed, 'destroyed');
|
|
383
|
+
|
|
384
|
+
const sdf = this.#sdf;
|
|
385
|
+
|
|
386
|
+
if (sdf.voxel_size !== this.#voxel_size || sdf.max_bricks !== this.#max_bricks) {
|
|
387
|
+
// a cut for the old voxel bakes a proxy finer or coarser than the cache it is for
|
|
388
|
+
this.#restart();
|
|
389
|
+
|
|
390
|
+
this.#voxel_size = sdf.voxel_size;
|
|
391
|
+
this.#max_bricks = sdf.max_bricks;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
this.#adopt();
|
|
395
|
+
this.#build();
|
|
396
|
+
this.#start();
|
|
397
|
+
|
|
398
|
+
if (this.#runtime.frame_open) {
|
|
399
|
+
this.#record(graph);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Give each geometry whose proxy is baked its cache, and remove the proxy.
|
|
405
|
+
*/
|
|
406
|
+
#adopt() {
|
|
407
|
+
const sdf = this.#sdf;
|
|
408
|
+
|
|
409
|
+
for (const job of this.#jobs) {
|
|
410
|
+
if (job.phase !== JOB_BAKED) {
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (sdf.adopt(job.record, job.proxy_record)) {
|
|
415
|
+
this.#adopted_count++;
|
|
416
|
+
} else if (sdf.is_requested(job.record)) {
|
|
417
|
+
// the proxy's cache is not the one it was baked to: a proxy equal to another's is that one's record
|
|
418
|
+
this.#requested.push(job.record);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
this.#free(job);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Build the proxy of the first job whose mesh is read back, and hold its cache.
|
|
427
|
+
*/
|
|
428
|
+
#build() {
|
|
429
|
+
if (!this.#clusterizer_ready) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const sdf = this.#sdf;
|
|
434
|
+
|
|
435
|
+
for (const job of this.#jobs) {
|
|
436
|
+
if (job.phase !== JOB_BUILD) {
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (!sdf.is_requested(job.record)) {
|
|
441
|
+
// let go since its cut was taken
|
|
442
|
+
this.#free(job);
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const mesh = new Geometry();
|
|
447
|
+
|
|
448
|
+
mesh.name = 'vgeo sdf proxy';
|
|
449
|
+
mesh.index = Attribute.from(job.indices, 1, StandardAttributes.Index);
|
|
450
|
+
mesh.addAttribute(Attribute.from(job.positions, 3, StandardAttributes.Position));
|
|
451
|
+
|
|
452
|
+
const proxy = meshlet_geometry_build_from_geometry(mesh);
|
|
453
|
+
|
|
454
|
+
this.#geometries.add(proxy);
|
|
455
|
+
|
|
456
|
+
job.proxy = proxy;
|
|
457
|
+
job.proxy_record = this.#geometries.get_metadata(proxy);
|
|
458
|
+
job.positions = null;
|
|
459
|
+
job.indices = null;
|
|
460
|
+
job.phase = JOB_BAKING;
|
|
461
|
+
|
|
462
|
+
this.#extracted_count++;
|
|
463
|
+
this.#triangles_extracted += job.triangle_count;
|
|
464
|
+
|
|
465
|
+
sdf.acquire(job.proxy_record, sdf.holds_two_sided(job.record));
|
|
466
|
+
|
|
467
|
+
if (sdf.state_of(job.proxy_record) === MeshSDFState.Resident) {
|
|
468
|
+
// a record a resident proxy of the same mesh already had
|
|
469
|
+
job.phase = JOB_BAKED;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Give the free slots the geometries asked for, in the order asked.
|
|
478
|
+
*/
|
|
479
|
+
#start() {
|
|
480
|
+
const sdf = this.#sdf;
|
|
481
|
+
const requested = this.#requested;
|
|
482
|
+
const layout = this.#layout;
|
|
483
|
+
|
|
484
|
+
let taken = 0;
|
|
485
|
+
|
|
486
|
+
for (const job of this.#jobs) {
|
|
487
|
+
if (job.phase !== JOB_FREE) {
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
while (taken < requested.length) {
|
|
492
|
+
const record = requested[taken++];
|
|
493
|
+
|
|
494
|
+
if (!sdf.is_requested(record) || this.#extracting(record)) {
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
layout.compute(record.geometry.bounding_box, sdf.voxel_size, sdf.max_bricks);
|
|
499
|
+
|
|
500
|
+
job.generation++;
|
|
501
|
+
job.record = record;
|
|
502
|
+
job.projection_k = 1 / (0.5 * layout.voxel);
|
|
503
|
+
job.phase = JOB_CUT;
|
|
504
|
+
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
requested.copyWithin(0, taken);
|
|
510
|
+
requested.length -= taken;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* @param {GPUGeometryMetadata} record
|
|
515
|
+
* @returns {boolean} whether a job holds it
|
|
516
|
+
*/
|
|
517
|
+
#extracting(record) {
|
|
518
|
+
for (const job of this.#jobs) {
|
|
519
|
+
if (job.phase !== JOB_FREE && job.record === record) {
|
|
520
|
+
return true;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Let every job go, and ask again for the geometries still asked for.
|
|
529
|
+
*/
|
|
530
|
+
#restart() {
|
|
531
|
+
for (const job of this.#jobs) {
|
|
532
|
+
if (job.phase === JOB_FREE) {
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (this.#sdf.is_requested(job.record)) {
|
|
537
|
+
this.#requested.push(job.record);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
this.#free(job);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* @param {VGeoSDFJob} job
|
|
546
|
+
*/
|
|
547
|
+
#free(job) {
|
|
548
|
+
if (job.proxy !== null) {
|
|
549
|
+
this.#geometries.remove(job.proxy);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
job.phase = JOB_FREE;
|
|
553
|
+
job.record = null;
|
|
554
|
+
job.positions = null;
|
|
555
|
+
job.indices = null;
|
|
556
|
+
job.proxy = null;
|
|
557
|
+
job.proxy_record = null;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* @returns {VGeoSDFFrame|null}
|
|
562
|
+
*/
|
|
563
|
+
#take_frame() {
|
|
564
|
+
for (const frame of this.#frames) {
|
|
565
|
+
if (!frame.busy) {
|
|
566
|
+
return frame;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return null;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Record the cut of the jobs that cut, and the write-out of those whose last cut stood nothing in.
|
|
575
|
+
*
|
|
576
|
+
* @param {FrameGraph} graph
|
|
577
|
+
*/
|
|
578
|
+
#record(graph) {
|
|
579
|
+
const frame = this.#take_frame();
|
|
580
|
+
|
|
581
|
+
if (frame === null) {
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const runtime = this.#runtime;
|
|
586
|
+
const view = this.#jobs_scratch;
|
|
587
|
+
const stride = VGEO_SDF_JOB_STRUCT.size;
|
|
588
|
+
|
|
589
|
+
let count = 0;
|
|
590
|
+
let vertices = 0;
|
|
591
|
+
let triangles = 0;
|
|
592
|
+
|
|
593
|
+
for (const job of this.#jobs) {
|
|
594
|
+
if (job.phase !== JOB_CUT && job.phase !== JOB_READY) {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (!this.#sdf.is_requested(job.record)) {
|
|
599
|
+
// let go since it was asked for: dropped, or forgotten
|
|
600
|
+
this.#free(job);
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const decode = job.phase === JOB_READY;
|
|
605
|
+
const at = count * stride;
|
|
606
|
+
|
|
607
|
+
frame.jobs[count] = job;
|
|
608
|
+
frame.generations[count] = job.generation;
|
|
609
|
+
frame.decoding[count] = decode ? 1 : 0;
|
|
610
|
+
frame.vertex_bases[count] = vertices;
|
|
611
|
+
frame.triangle_bases[count] = triangles;
|
|
612
|
+
|
|
613
|
+
view.setUint32(at + VGEO_SDF_JOB_STRUCT.get("vg_row").offset, job.record.vg_row, true);
|
|
614
|
+
view.setFloat32(at + VGEO_SDF_JOB_STRUCT.get("projection_k").offset, job.projection_k, true);
|
|
615
|
+
view.setUint32(at + VGEO_SDF_JOB_STRUCT.get("decode").offset, decode ? 1 : 0, true);
|
|
616
|
+
view.setUint32(at + VGEO_SDF_JOB_STRUCT.get("vertex_base").offset, vertices, true);
|
|
617
|
+
view.setUint32(at + VGEO_SDF_JOB_STRUCT.get("triangle_base").offset, triangles, true);
|
|
618
|
+
view.setUint32(at + VGEO_SDF_JOB_STRUCT.get("vertex_count").offset, decode ? job.vertex_count : 0, true);
|
|
619
|
+
view.setUint32(at + VGEO_SDF_JOB_STRUCT.get("triangle_count").offset, decode ? job.triangle_count : 0, true);
|
|
620
|
+
|
|
621
|
+
if (decode) {
|
|
622
|
+
vertices += job.vertex_count;
|
|
623
|
+
triangles += job.triangle_count;
|
|
624
|
+
job.phase = JOB_DECODING;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
count++;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
if (count === 0) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
frame.busy = true;
|
|
635
|
+
frame.count = count;
|
|
636
|
+
|
|
637
|
+
const header_words = vgeo_sdf_header_words(count);
|
|
638
|
+
|
|
639
|
+
frame.vertex_offset = header_words;
|
|
640
|
+
frame.index_offset = header_words + 3 * vertices;
|
|
641
|
+
|
|
642
|
+
const payload_bytes = 4 * (frame.index_offset + 3 * triangles);
|
|
643
|
+
|
|
644
|
+
this.#device.queue.writeBuffer(this.#jobs_buffer, 0, view.buffer, 0, count * stride);
|
|
645
|
+
|
|
646
|
+
const settings = this.#settings;
|
|
647
|
+
|
|
648
|
+
settings.job_count = count;
|
|
649
|
+
settings.cluster_capacity = this.#cluster_capacity;
|
|
650
|
+
settings.vertex_offset = frame.vertex_offset;
|
|
651
|
+
settings.index_offset = frame.index_offset;
|
|
652
|
+
|
|
653
|
+
// this frame's slot for the cut, and its params: a τ of 1, since its records carry the error's own scale
|
|
654
|
+
const slot = runtime.slot_of(this.#cut);
|
|
655
|
+
|
|
656
|
+
this.#cut.write_params({ runtime, slot, tau: 1 });
|
|
657
|
+
this.#stats_base = vgeo_feedback_slot_stats(slot);
|
|
658
|
+
|
|
659
|
+
// ----- the records: a job's geometry whole, then their claim widths scanned -----
|
|
660
|
+
|
|
661
|
+
const collect_data = this.#collect_data;
|
|
662
|
+
const collect = graph.add("VGeo SDF Collect", collect_data, this.#execute_collect);
|
|
663
|
+
|
|
664
|
+
collect_data.instances = collect.create("vgeo sdf instances", BufferResourceDescriptor.from(
|
|
665
|
+
count * VGEO_INSTANCE_WORDS * 4, GPUBufferUsage.STORAGE
|
|
666
|
+
));
|
|
667
|
+
collect_data.claim_widths = collect.create("vgeo sdf claim widths", BufferResourceDescriptor.from(
|
|
668
|
+
16 + count * 4, GPUBufferUsage.STORAGE, 0, 16
|
|
669
|
+
));
|
|
670
|
+
|
|
671
|
+
const prefix_sums = graph_prefix_scan_csdldf({
|
|
672
|
+
graph,
|
|
673
|
+
input: collect_data.claim_widths,
|
|
674
|
+
output: graph_create_buffer(graph, "vgeo sdf claim offsets", prefix_scan_csdldf_output_descriptor(count)),
|
|
675
|
+
element_max_count: count,
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
// ----- the cut: the camera cut's own descent, its clusters onto the list -----
|
|
679
|
+
|
|
680
|
+
const counters = graph_create_buffer(graph, "vgeo sdf counters", BufferResourceDescriptor.empty(
|
|
681
|
+
count * VGEO_SDF_COUNTER_WORDS * 4, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
682
|
+
));
|
|
683
|
+
const clusters = graph_create_buffer(graph, "vgeo sdf clusters", BufferResourceDescriptor.from(
|
|
684
|
+
16 + this.#cluster_capacity * VGEO_SDF_CLUSTER_WORDS * 4, GPUBufferUsage.STORAGE, 0, 16
|
|
685
|
+
));
|
|
686
|
+
|
|
687
|
+
const descent = graph_vgeo_cut_descent({
|
|
688
|
+
graph,
|
|
689
|
+
runtime,
|
|
690
|
+
cut: this.#cut,
|
|
691
|
+
instances: collect_data.instances,
|
|
692
|
+
prefix_sums,
|
|
693
|
+
feedback: runtime.feedback_in(graph),
|
|
694
|
+
traverse: shader_vgeo_sdf_traverse,
|
|
695
|
+
bindings: { settings },
|
|
696
|
+
outputs: { vgeo_sdf_counters: counters, vgeo_sdf_clusters: clusters },
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
runtime.publish_feedback(graph, descent.feedback);
|
|
700
|
+
|
|
701
|
+
// ----- the write-out: a workgroup a listed cluster, every job's sizes and the ready jobs' meshes -----
|
|
702
|
+
|
|
703
|
+
const command = graph_build_indirect_dispatch_command(graph, descent.outputs.vgeo_sdf_clusters, 1, true);
|
|
704
|
+
|
|
705
|
+
const decode_data = this.#decode_data;
|
|
706
|
+
const decode = graph.add("VGeo SDF Decode", decode_data, this.#execute_decode);
|
|
707
|
+
|
|
708
|
+
decode_data.command = decode.read(command);
|
|
709
|
+
decode_data.clusters = decode.read(descent.outputs.vgeo_sdf_clusters);
|
|
710
|
+
decode_data.counters = decode.write(descent.outputs.vgeo_sdf_counters);
|
|
711
|
+
decode_data.payload = decode.create("vgeo sdf payload", BufferResourceDescriptor.from(
|
|
712
|
+
payload_bytes, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
|
|
713
|
+
));
|
|
714
|
+
|
|
715
|
+
// ----- the header: the jobs' counters and the cut's own, ahead of the meshes, then read back -----
|
|
716
|
+
|
|
717
|
+
const header_data = this.#header_data;
|
|
718
|
+
const header = graph.add("VGeo SDF Header", header_data, this.#execute_header);
|
|
719
|
+
|
|
720
|
+
header_data.counters = header.read(decode_data.counters);
|
|
721
|
+
header_data.feedback = header.read(descent.feedback);
|
|
722
|
+
header_data.payload = header.write(decode_data.payload);
|
|
723
|
+
|
|
724
|
+
graph_read_buffer({ graph, buffer: header_data.payload, offset: 0, size: payload_bytes })
|
|
725
|
+
.then(reference => {
|
|
726
|
+
try {
|
|
727
|
+
if (!this.#destroyed) {
|
|
728
|
+
this.#apply(new Uint32Array(reference.getValue()), frame);
|
|
729
|
+
}
|
|
730
|
+
} finally {
|
|
731
|
+
reference.release();
|
|
732
|
+
}
|
|
733
|
+
})
|
|
734
|
+
.catch(error => {
|
|
735
|
+
if (!this.#destroyed) {
|
|
736
|
+
console.warn('VGeoSDFProxies: readback failed', error);
|
|
737
|
+
this.#lose(frame);
|
|
738
|
+
}
|
|
739
|
+
})
|
|
740
|
+
.finally(() => {
|
|
741
|
+
frame.busy = false;
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
#execute_collect = (data, resources, execution) => {
|
|
746
|
+
const b = this.#collect_bindings;
|
|
747
|
+
|
|
748
|
+
b.settings = this.#settings;
|
|
749
|
+
b.vgeo_sdf_jobs = this.#jobs_buffer;
|
|
750
|
+
b.vg_geometries = this.#runtime.pool.buffer_geometries;
|
|
751
|
+
b.instances = resources.get(data.instances);
|
|
752
|
+
b.claim_widths = resources.get(data.claim_widths);
|
|
753
|
+
|
|
754
|
+
shader_vgeo_sdf_collect.dispatch({
|
|
755
|
+
encoder: execution.encoder,
|
|
756
|
+
group_count_x: Math.ceil(this.#settings.job_count / VGEO_SDF_COLLECT_WORKGROUP_SIZE),
|
|
757
|
+
bindings: b,
|
|
758
|
+
});
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
#execute_decode = (data, resources, execution) => {
|
|
762
|
+
const meshlets = this.#geometries.meshlets;
|
|
763
|
+
const b = this.#decode_bindings;
|
|
764
|
+
|
|
765
|
+
b.settings = this.#settings;
|
|
766
|
+
b.vgeo_sdf_jobs = this.#jobs_buffer;
|
|
767
|
+
b.vgeo_sdf_counters = resources.get(data.counters);
|
|
768
|
+
b.vgeo_sdf_clusters = resources.get(data.clusters);
|
|
769
|
+
b.meshlet_metadata = meshlets.buffer_metadata;
|
|
770
|
+
b.meshlet_data = meshlets.buffer_data;
|
|
771
|
+
b.vgeo_sdf_payload = resources.get(data.payload);
|
|
772
|
+
|
|
773
|
+
shader_vgeo_sdf_decode.dispatchIndirect({
|
|
774
|
+
encoder: execution.encoder,
|
|
775
|
+
command: resources.get(data.command),
|
|
776
|
+
command_offset: 0,
|
|
777
|
+
bindings: b,
|
|
778
|
+
});
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
#execute_header = (data, resources, execution) => {
|
|
782
|
+
const encoder = execution.encoder;
|
|
783
|
+
const payload = resources.get(data.payload);
|
|
784
|
+
const counter_bytes = 4 * this.#settings.job_count * VGEO_SDF_COUNTER_WORDS;
|
|
785
|
+
|
|
786
|
+
encoder.copyBufferToBuffer(resources.get(data.counters), 0, payload, 0, counter_bytes);
|
|
787
|
+
encoder.copyBufferToBuffer(resources.get(data.feedback), 4 * this.#stats_base, payload, counter_bytes, 4 * VGEO_CUT_STAT_COUNT);
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* A recorded frame's readback: each job's cut taken, its mesh too where the frame wrote it out.
|
|
792
|
+
*
|
|
793
|
+
* @param {Uint32Array} words
|
|
794
|
+
* @param {VGeoSDFFrame} frame
|
|
795
|
+
*/
|
|
796
|
+
#apply(words, frame) {
|
|
797
|
+
const stats = frame.count * VGEO_SDF_COUNTER_WORDS;
|
|
798
|
+
|
|
799
|
+
// a subtree the cut left undescended is missing from every job's list, and no counter of a job says which
|
|
800
|
+
const holes = words[stats + VGEO_CUT_STAT.QUEUE_DROPPED] > 0
|
|
801
|
+
|| words[stats + VGEO_CUT_STAT.QUEUE_REMAINING] > 0
|
|
802
|
+
|| words[stats + VGEO_CUT_STAT.INSTANCES_DROPPED] > 0;
|
|
803
|
+
|
|
804
|
+
let taken = 0;
|
|
805
|
+
let dropped = false;
|
|
806
|
+
|
|
807
|
+
for (let i = 0; i < frame.count; i++) {
|
|
808
|
+
const job = frame.jobs[i];
|
|
809
|
+
const c = i * VGEO_SDF_COUNTER_WORDS;
|
|
810
|
+
|
|
811
|
+
taken += words[c + VGEO_SDF_COUNTER.TAKEN];
|
|
812
|
+
dropped ||= words[c + VGEO_SDF_COUNTER.DROPPED] > 0;
|
|
813
|
+
|
|
814
|
+
if (job.generation !== frame.generations[i]) {
|
|
815
|
+
// the slot holds another geometry now
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
const complete = !holes
|
|
820
|
+
&& words[c + VGEO_SDF_COUNTER.TAKEN] > 0
|
|
821
|
+
&& words[c + VGEO_SDF_COUNTER.STAND_INS] === 0
|
|
822
|
+
&& words[c + VGEO_SDF_COUNTER.DROPPED] === 0;
|
|
823
|
+
|
|
824
|
+
if (frame.decoding[i] === 0) {
|
|
825
|
+
if (job.phase === JOB_CUT && complete) {
|
|
826
|
+
job.vertex_count = words[c + VGEO_SDF_COUNTER.VERTICES];
|
|
827
|
+
job.triangle_count = words[c + VGEO_SDF_COUNTER.TRIANGLES];
|
|
828
|
+
job.phase = JOB_READY;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
if (job.phase !== JOB_DECODING) {
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
const whole = complete
|
|
839
|
+
&& words[c + VGEO_SDF_COUNTER.VERTICES] === job.vertex_count
|
|
840
|
+
&& words[c + VGEO_SDF_COUNTER.TRIANGLES] === job.triangle_count
|
|
841
|
+
&& words[c + VGEO_SDF_COUNTER.VERTICES_WRITTEN] === job.vertex_count
|
|
842
|
+
&& words[c + VGEO_SDF_COUNTER.TRIANGLES_WRITTEN] === job.triangle_count;
|
|
843
|
+
|
|
844
|
+
if (!whole) {
|
|
845
|
+
// cut otherwise than the cut its room was made for
|
|
846
|
+
job.phase = JOB_CUT;
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
const first_vertex = frame.vertex_offset + 3 * frame.vertex_bases[i];
|
|
851
|
+
const first_index = frame.index_offset + 3 * frame.triangle_bases[i];
|
|
852
|
+
|
|
853
|
+
job.positions = new Float32Array(words.buffer, words.byteOffset + 4 * first_vertex, 3 * job.vertex_count).slice();
|
|
854
|
+
job.indices = words.slice(first_index, first_index + 3 * job.triangle_count);
|
|
855
|
+
job.phase = JOB_BUILD;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
if (dropped) {
|
|
859
|
+
while (this.#cluster_capacity < taken) {
|
|
860
|
+
this.#cluster_capacity *= 2;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* A frame whose readback was lost: the jobs it wrote out are cut again.
|
|
867
|
+
*
|
|
868
|
+
* @param {VGeoSDFFrame} frame
|
|
869
|
+
*/
|
|
870
|
+
#lose(frame) {
|
|
871
|
+
for (let i = 0; i < frame.count; i++) {
|
|
872
|
+
const job = frame.jobs[i];
|
|
873
|
+
|
|
874
|
+
if (frame.decoding[i] === 1 && job.generation === frame.generations[i] && job.phase === JOB_DECODING) {
|
|
875
|
+
job.phase = JOB_CUT;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
destroy() {
|
|
881
|
+
if (this.#destroyed) {
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
this.#destroyed = true;
|
|
886
|
+
|
|
887
|
+
const sdf = this.#sdf;
|
|
888
|
+
|
|
889
|
+
sdf.remove_source(this);
|
|
890
|
+
sdf.onRequested.remove(this.#requested_one, this);
|
|
891
|
+
sdf.onBaked.remove(this.#baked, this);
|
|
892
|
+
|
|
893
|
+
for (const job of this.#jobs) {
|
|
894
|
+
this.#free(job);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
this.#requested.length = 0;
|
|
898
|
+
|
|
899
|
+
this.#cut.destroy();
|
|
900
|
+
this.#jobs_buffer.destroy();
|
|
901
|
+
}
|
|
902
|
+
}
|