@woosh/meep-engine 3.25.0 → 3.27.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/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +542 -0
- package/src/core/binary/lz4/LZ4_LEVEL.d.ts +33 -0
- package/src/core/binary/lz4/LZ4_LEVEL.d.ts.map +1 -0
- package/src/core/binary/lz4/LZ4_LEVEL.js +32 -0
- package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts +33 -0
- package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts.map +1 -0
- package/src/core/binary/lz4/lz4_compress_block_at_level.js +47 -0
- package/src/core/binary/lz4/lz4_compress_block_hc.d.ts +40 -0
- package/src/core/binary/lz4/lz4_compress_block_hc.d.ts.map +1 -0
- package/src/core/binary/lz4/lz4_compress_block_hc.js +1382 -0
- package/src/core/binary/lz4/lz4_decompress_block.d.ts +2 -1
- package/src/core/binary/lz4/lz4_decompress_block.d.ts.map +1 -1
- package/src/core/binary/lz4/lz4_decompress_block.js +31 -6
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +66 -0
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.js +314 -20
- package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/PosedShape3D.js +57 -0
- package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/TransformedShape3D.js +102 -0
- package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnionShape3D.js +64 -0
- package/src/engine/physics/cloth/MEASUREMENTS.md +582 -0
- package/src/engine/physics/cloth/PLAN.md +330 -49
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +84 -17
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/ClothColliderIndex.js +451 -42
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +65 -7
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +72 -8
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +25 -4
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +75 -8
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +41 -4
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +207 -63
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +10 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +17 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +27 -3
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +28 -3
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +75 -10
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +131 -12
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +19 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +249 -201
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +62 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +18 -10
- package/src/engine/physics/cloth/playground/collide_main.js +1 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +29 -8
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.js +37 -9
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +12 -2
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +12 -2
- package/src/engine/physics/cloth/solver/cloth_step_instance.js +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +9 -2
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +9 -2
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +23 -9
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/AbstractClothWind.js +23 -9
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +7 -5
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/ClothAmbientWind.js +12 -9
- package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/ClothFluidWind.js +5 -2
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +7 -2
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/cloth_sample_air.js +12 -5
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/playground/vgeo_runtime/README.md +167 -22
- package/src/shade/playground/vgeo_runtime/index.html +112 -62
- package/src/shade/playground/vgeo_runtime/main.js +660 -83
- package/src/shade/playground/vgeo_viewer/sample_asset.d.ts.map +1 -1
- package/src/shade/playground/vgeo_viewer/sample_asset.js +19 -2
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +11 -0
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +16 -8
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +16 -11
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +73 -5
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +26 -15
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +5 -3
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +18 -0
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +20 -0
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +56 -9
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +1 -0
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +22 -0
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +24 -0
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts +12 -0
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +13 -0
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts +8 -1
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +11 -3
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +10 -1
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts +18 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.js +17 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts +8 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.js +7 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.js +13 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts +11 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.js +10 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +20 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +20 -2
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +4 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +4 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +29 -3
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +81 -122
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +40 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +44 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts +69 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.js +236 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +15 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts +31 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.js +32 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +10 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +21 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.js +84 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts +22 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.js +96 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +55 -0
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +202 -13
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +147 -10
- package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +637 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +33 -36
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +109 -193
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +58 -28
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +77 -105
- package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +37 -0
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +105 -22
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +548 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +29 -50
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +47 -489
- package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts +84 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js +393 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts +234 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js +1363 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts +81 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.js +89 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +53 -34
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +407 -124
- package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts +100 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.js +219 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.js +47 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts +20 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.js +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +30 -12
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +15 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +18 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +5 -15
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.js +77 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.js +186 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +20 -8
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +580 -188
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +15 -18
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +19 -28
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +45 -25
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +11 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +0 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +12 -10
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +7 -2
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +8 -3
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +2 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts +5 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.js +22 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.js +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.js +16 -0
- package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.js +16 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts +23 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.js +28 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts +2 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.js +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +10 -5
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +15 -6
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +6 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +38 -1
- 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 +4 -3
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +6 -3
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +6 -3
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- 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 +12 -4
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +2 -0
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +58 -57
- 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 +3 -5
- 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 +3 -4
- 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 +3 -4
- package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.js +7 -7
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +83 -78
- 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 +7 -1
- 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 +7 -1
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +22 -2
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +59 -4
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +92 -16
- package/src/shade/renderer/view/GPUViewContext.d.ts +5 -0
- package/src/shade/renderer/view/GPUViewContext.d.ts.map +1 -1
- package/src/shade/renderer/view/GPUViewContext.js +21 -0
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +74 -3
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +0 -723
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +0 -50
- package/src/shade/renderer/shader/chunk/jobs/NOTES.md +0 -47
- package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.js +0 -102
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* is on screen, which is the fallback-chain bug `VTPhysicalCache` already keys on touch to avoid.
|
|
19
19
|
*
|
|
20
20
|
* **Two budgets, and both of them bind.** Slots are fixed and finite, so a full table is as real a
|
|
21
|
-
* reason to evict as a full byte budget;
|
|
21
|
+
* reason to evict as a full byte budget; `VGeoResidency` makes room on whichever of the two is short.
|
|
22
22
|
*
|
|
23
23
|
* @author Alex Goldring
|
|
24
24
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -29,19 +29,13 @@ export class GPUVirtualGeometryPool {
|
|
|
29
29
|
* @param {GPUDevice} options.device
|
|
30
30
|
* @param {GPUMeshletManager} options.meshlets the pool VG shares with static geometry, so a VG
|
|
31
31
|
* draw record is read downstream by the same shader that reads a static one
|
|
32
|
-
* @param {number} [options.budget_bytes] decoded page bytes this tier may hold; defaults to
|
|
33
|
-
* what its slots hold at the page size it was built for, so the two agree by construction
|
|
34
|
-
* @param {number} [options.protect_window] frames a touched page is safe for; no shorter than
|
|
35
|
-
* feedback latency, which is at least one frame of `mapAsync` and in practice several
|
|
36
32
|
* @param {Object} [options.table_options] passed to {@link VGeoRuntimeTables}
|
|
37
33
|
* @param {number} [options.page_size] the page size every container registered here must have
|
|
38
34
|
* been built at, and the one this tier's slots are sized from
|
|
39
35
|
*/
|
|
40
|
-
constructor({ device, meshlets,
|
|
36
|
+
constructor({ device, meshlets, table_options, page_size, }: {
|
|
41
37
|
device: GPUDevice;
|
|
42
38
|
meshlets: GPUMeshletManager;
|
|
43
|
-
budget_bytes?: number;
|
|
44
|
-
protect_window?: number;
|
|
45
39
|
table_options?: any;
|
|
46
40
|
page_size?: number;
|
|
47
41
|
});
|
|
@@ -58,6 +52,11 @@ export class GPUVirtualGeometryPool {
|
|
|
58
52
|
* @returns {GPUBuffer}
|
|
59
53
|
*/
|
|
60
54
|
get buffer_geometries(): GPUBuffer;
|
|
55
|
+
/**
|
|
56
|
+
* The persistent, frame-tagged want stamps, one per lookup word.
|
|
57
|
+
* @returns {GPUBuffer}
|
|
58
|
+
*/
|
|
59
|
+
get buffer_want_stamps(): GPUBuffer;
|
|
61
60
|
/**
|
|
62
61
|
* @returns {VGeoRuntimeTables}
|
|
63
62
|
*/
|
|
@@ -66,10 +65,6 @@ export class GPUVirtualGeometryPool {
|
|
|
66
65
|
* @returns {number}
|
|
67
66
|
*/
|
|
68
67
|
get resident_bytes(): number;
|
|
69
|
-
/**
|
|
70
|
-
* @returns {number}
|
|
71
|
-
*/
|
|
72
|
-
get budget_bytes(): number;
|
|
73
68
|
/**
|
|
74
69
|
* The page size every container registered here is required to have been built at.
|
|
75
70
|
* @returns {number}
|
|
@@ -88,14 +83,28 @@ export class GPUVirtualGeometryPool {
|
|
|
88
83
|
*/
|
|
89
84
|
get evicted_page_count(): number;
|
|
90
85
|
/**
|
|
91
|
-
*
|
|
86
|
+
* The decoded bytes a resident row was charged for, out of its own slot.
|
|
87
|
+
*
|
|
88
|
+
* @param {number} page_row
|
|
92
89
|
* @returns {number}
|
|
93
90
|
*/
|
|
94
|
-
|
|
91
|
+
bytes_of(page_row: number): number;
|
|
92
|
+
/**
|
|
93
|
+
* @param {number} page_row
|
|
94
|
+
* @returns {number} the container page index a resident row holds
|
|
95
|
+
*/
|
|
96
|
+
page_index_of(page_row: number): number;
|
|
95
97
|
/**
|
|
96
98
|
* @returns {number}
|
|
97
99
|
*/
|
|
98
100
|
get frame(): number;
|
|
101
|
+
/**
|
|
102
|
+
* The frame whose flush publishes this row's current occupant, or `0xFFFFFFFF` for none.
|
|
103
|
+
*
|
|
104
|
+
* @param {number} page_row
|
|
105
|
+
* @returns {number}
|
|
106
|
+
*/
|
|
107
|
+
visible_from(page_row: number): number;
|
|
99
108
|
/**
|
|
100
109
|
* One past the highest page row handed out — what sizes the feedback buffer's touch stamps.
|
|
101
110
|
* @returns {number}
|
|
@@ -106,11 +115,13 @@ export class GPUVirtualGeometryPool {
|
|
|
106
115
|
*/
|
|
107
116
|
get lookup_word_count(): number;
|
|
108
117
|
/**
|
|
109
|
-
* Give a container a geometry row
|
|
118
|
+
* Give a container a geometry row and a block of the lookup, with every page absent.
|
|
110
119
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
120
|
+
* Nothing resident, not even the root: which pages are here is `VGeoResidency`'s decision and it
|
|
121
|
+
* installs the root through the same door as every other page, pinned in its own tables. A
|
|
122
|
+
* geometry whose root is not here draws nothing — every traversal is seeded with it, invariant
|
|
123
|
+
* §11.7 puts exactly one root cluster in the file — and the residency throws on a registration
|
|
124
|
+
* that cannot make it resident, rolling this back.
|
|
114
125
|
*
|
|
115
126
|
* This is also the door the page-size guarantee is checked at, because it is the last moment a
|
|
116
127
|
* refusal is still cheap: past it, this container's pages are laid into the tier's storage on
|
|
@@ -188,28 +199,12 @@ export class GPUVirtualGeometryPool {
|
|
|
188
199
|
row: number;
|
|
189
200
|
} | undefined;
|
|
190
201
|
/**
|
|
191
|
-
*
|
|
202
|
+
* The runtime calls this at `begin_frame`, before the flush; see {@link visible_from} for why
|
|
203
|
+
* the order matters.
|
|
192
204
|
*
|
|
193
|
-
* @param {number} page_row
|
|
194
|
-
* @returns {void}
|
|
195
|
-
*/
|
|
196
|
-
touch(page_row: number): void;
|
|
197
|
-
/**
|
|
198
205
|
* @returns {void}
|
|
199
206
|
*/
|
|
200
207
|
advance_frame(): void;
|
|
201
|
-
/**
|
|
202
|
-
* Whether a page may go: not pinned, not touched inside the protect window, and with no VRAM
|
|
203
|
-
* child.
|
|
204
|
-
*
|
|
205
|
-
* The child rule is this tier's own, out of this tier's tables. Dropping a parent while its
|
|
206
|
-
* children stay leaves those children unreachable — nothing refines into them any more — so
|
|
207
|
-
* they would sit in VRAM, selectable, and never drawn.
|
|
208
|
-
*
|
|
209
|
-
* @param {number} page_row
|
|
210
|
-
* @returns {boolean}
|
|
211
|
-
*/
|
|
212
|
-
evictable(page_row: number): boolean;
|
|
213
208
|
/**
|
|
214
209
|
* Push everything that changed since the last call to the device.
|
|
215
210
|
*
|
|
@@ -224,5 +219,7 @@ export class GPUVirtualGeometryPool {
|
|
|
224
219
|
destroy(): void;
|
|
225
220
|
#private;
|
|
226
221
|
}
|
|
222
|
+
export type GPUMeshletManager = import("../../meshlet/GPUMeshletManager.js").GPUMeshletManager;
|
|
223
|
+
export type VGeoContainerReader = import("../format/read/VGeoContainerReader.js").VGeoContainerReader;
|
|
227
224
|
import { VGeoRuntimeTables } from "./VGeoRuntimeTables.js";
|
|
228
225
|
//# sourceMappingURL=GPUVirtualGeometryPool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GPUVirtualGeometryPool.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GPUVirtualGeometryPool.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js"],"names":[],"mappings":"AAmDA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH;IAoFI;;;;;;;;OAQG;IACH;QAP8B,MAAM;QACE,QAAQ,EAAnC,iBAAiB;QAEA,aAAa;QACb,SAAS,GAA1B,MAAM;OAyChB;IAkCD;;OAEG;IACH,+BAEC;IAED;;;OAGG;IACH,8BAEC;IAED;;OAEG;IACH,mCAEC;IAED;;;OAGG;IACH,oCAEC;IAED;;OAEG;IACH,gCAEC;IAED;;OAEG;IACH,6BAEC;IAGD;;;OAGG;IACH,wBAEC;IAED;;OAEG;IACH,8BAEC;IAED;;OAEG;IACH,kCAEC;IAED;;OAEG;IACH,iCAEC;IAED;;;;;OAKG;IACH,mBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,wBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;OAEG;IACH,oBAEC;IAED;;;;;OAKG;IACH,uBAHW,MAAM,GACJ,MAAM,CAQlB;IAED;;;OAGG;IACH,gCAEC;IAED;;OAEG;IACH,gCAEC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,iBALW,mBAAmB,GACjB,MAAM,CAmClB;IAED;;;;;;;;;OASG;IACH,mBAHW,mBAAmB,GACjB,OAAO,CA+CnB;IAqCD;;;OAGG;IACH,wBAHW,mBAAmB,GACjB,MAAM,CAIlB;IAED;;;;OAIG;IACH,oBAJW,mBAAmB,cACnB,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;;OAOG;IACH,wBAJW,mBAAmB,cACnB,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,gBAJW,mBAAmB,cACnB,MAAM,GACJ,MAAM,CAgElB;IAED;;;OAGG;IACH,gBAHW,MAAM,GACJ,OAAO,CA0CnB;IAED;;;;;;;;;;;;;;OAcG;IACH,mBAHW,MAAM,GACJ;QAAC,MAAM,EAAE,mBAAmB,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAC,GAAC,SAAS,CAIhE;IAED;;;;;OAKG;IACH,iBAFa,IAAI,CAIhB;IA2ED;;;;;;;;;OASG;IACH,SAFa,IAAI,CAMhB;IAwDD,gBAcC;;CACJ;gCAp0BY,OAAO,oCAAoC,EAAE,iBAAiB;kCAC9D,OAAO,uCAAuC,EAAE,mBAAmB;kCAL9C,wBAAwB"}
|
|
@@ -8,6 +8,11 @@ import { VGEO_PAGE_ROW_WORDS } from "./layout/VGEO_PAGE_ROW_WORDS.js";
|
|
|
8
8
|
import { VGeoRuntimeTables } from "./VGeoRuntimeTables.js";
|
|
9
9
|
import { vgeo_runtime_meshlet_batch } from "./vgeo_runtime_meshlet_batch.js";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {import("../../meshlet/GPUMeshletManager.js").GPUMeshletManager} GPUMeshletManager
|
|
13
|
+
* @typedef {import("../format/read/VGeoContainerReader.js").VGeoContainerReader} VGeoContainerReader
|
|
14
|
+
*/
|
|
15
|
+
|
|
11
16
|
/**
|
|
12
17
|
* One resident geometry's bookkeeping above the tables.
|
|
13
18
|
*/
|
|
@@ -64,7 +69,7 @@ class VGeoPoolGeometry {
|
|
|
64
69
|
* is on screen, which is the fallback-chain bug `VTPhysicalCache` already keys on touch to avoid.
|
|
65
70
|
*
|
|
66
71
|
* **Two budgets, and both of them bind.** Slots are fixed and finite, so a full table is as real a
|
|
67
|
-
* reason to evict as a full byte budget;
|
|
72
|
+
* reason to evict as a full byte budget; `VGeoResidency` makes room on whichever of the two is short.
|
|
68
73
|
*
|
|
69
74
|
* @author Alex Goldring
|
|
70
75
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -96,18 +101,6 @@ export class GPUVirtualGeometryPool {
|
|
|
96
101
|
*/
|
|
97
102
|
#owner = new Map();
|
|
98
103
|
|
|
99
|
-
/**
|
|
100
|
-
* Page row to the frame it was last selected from.
|
|
101
|
-
* @type {Map<number, number>}
|
|
102
|
-
*/
|
|
103
|
-
#touched = new Map();
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Page rows that may never go: the root page of every registered geometry, which is where every
|
|
107
|
-
* traversal starts and without which a geometry draws nothing at all.
|
|
108
|
-
* @type {Set<number>}
|
|
109
|
-
*/
|
|
110
|
-
#pinned = new Set();
|
|
111
104
|
|
|
112
105
|
/**
|
|
113
106
|
* Per page row, the unsubscribe for that page's meshlet batch relocation signal.
|
|
@@ -116,24 +109,32 @@ export class GPUVirtualGeometryPool {
|
|
|
116
109
|
#batch_listeners = new Map();
|
|
117
110
|
|
|
118
111
|
/**
|
|
112
|
+
* Advanced by the runtime at `begin_frame`, before the flush — so it is the number of the
|
|
113
|
+
* flush that publishes whatever is installed before it, and the flush after that publishes
|
|
114
|
+
* what lands later in the frame.
|
|
119
115
|
* @type {number}
|
|
120
116
|
*/
|
|
121
117
|
#frame = 0;
|
|
122
118
|
|
|
123
119
|
/**
|
|
124
|
-
*
|
|
120
|
+
* Per page row, the frame whose flush publishes the row's current occupant, or
|
|
121
|
+
* `0xFFFFFFFF` for a row with none.
|
|
122
|
+
*
|
|
123
|
+
* What a reading compares against, per record, instead of a snapshot of every row's generation
|
|
124
|
+
* per readback: a record from the cut of frame F naming row r is about r's occupant iff
|
|
125
|
+
* `visible_from[r] <= F`. An install stamps `frame + 1` — this frame's flush has already run
|
|
126
|
+
* — so a row refilled after the cut, in the same frame or later, is rejected by that cut's
|
|
127
|
+
* reading, and a freed row is rejected by every reading (RUNTIME_PLAN_2026_09_14 §2.4).
|
|
128
|
+
*
|
|
129
|
+
* @type {Uint32Array}
|
|
125
130
|
*/
|
|
126
|
-
#
|
|
131
|
+
#visible_from;
|
|
127
132
|
|
|
128
133
|
/**
|
|
129
134
|
* @type {number}
|
|
130
135
|
*/
|
|
131
|
-
#
|
|
136
|
+
#resident_bytes = 0;
|
|
132
137
|
|
|
133
|
-
/**
|
|
134
|
-
* @type {number}
|
|
135
|
-
*/
|
|
136
|
-
#protect_window;
|
|
137
138
|
|
|
138
139
|
/**
|
|
139
140
|
* @type {number}
|
|
@@ -156,20 +157,12 @@ export class GPUVirtualGeometryPool {
|
|
|
156
157
|
*/
|
|
157
158
|
#evicted_page_count = 0;
|
|
158
159
|
|
|
159
|
-
/**
|
|
160
|
-
* @type {number}
|
|
161
|
-
*/
|
|
162
|
-
#refused_install_count = 0;
|
|
163
160
|
|
|
164
161
|
/**
|
|
165
162
|
* @param {Object} options
|
|
166
163
|
* @param {GPUDevice} options.device
|
|
167
164
|
* @param {GPUMeshletManager} options.meshlets the pool VG shares with static geometry, so a VG
|
|
168
165
|
* draw record is read downstream by the same shader that reads a static one
|
|
169
|
-
* @param {number} [options.budget_bytes] decoded page bytes this tier may hold; defaults to
|
|
170
|
-
* what its slots hold at the page size it was built for, so the two agree by construction
|
|
171
|
-
* @param {number} [options.protect_window] frames a touched page is safe for; no shorter than
|
|
172
|
-
* feedback latency, which is at least one frame of `mapAsync` and in practice several
|
|
173
166
|
* @param {Object} [options.table_options] passed to {@link VGeoRuntimeTables}
|
|
174
167
|
* @param {number} [options.page_size] the page size every container registered here must have
|
|
175
168
|
* been built at, and the one this tier's slots are sized from
|
|
@@ -177,33 +170,36 @@ export class GPUVirtualGeometryPool {
|
|
|
177
170
|
constructor({
|
|
178
171
|
device,
|
|
179
172
|
meshlets,
|
|
180
|
-
budget_bytes = undefined,
|
|
181
|
-
protect_window = 4,
|
|
182
173
|
table_options = undefined,
|
|
183
174
|
page_size = VGEO_DEFAULT_PAGE_SIZE,
|
|
184
175
|
}) {
|
|
185
176
|
assert.defined(device, 'device');
|
|
186
177
|
assert.defined(meshlets, 'meshlets');
|
|
187
|
-
assert.isNonNegativeInteger(protect_window, 'protect_window');
|
|
188
178
|
assert.isPositiveInteger(page_size, 'page_size');
|
|
189
179
|
|
|
190
180
|
this.#device = device;
|
|
191
181
|
this.#meshlets = meshlets;
|
|
192
|
-
this.#protect_window = protect_window;
|
|
193
182
|
this.#page_size = page_size;
|
|
194
183
|
|
|
195
184
|
this.#tables = new VGeoRuntimeTables({ page_size, ...table_options });
|
|
196
185
|
|
|
197
|
-
this.#budget_bytes = budget_bytes ?? this.#tables.page_capacity * page_size;
|
|
198
|
-
|
|
199
|
-
assert.isNonNegativeInteger(this.#budget_bytes, 'budget_bytes');
|
|
200
186
|
|
|
201
187
|
this.#buffers = {
|
|
202
188
|
lookup: this.#create('lookup', this.#tables.lookup_words.byteLength),
|
|
203
189
|
arena: this.#create('arena', this.#tables.arena_words.byteLength),
|
|
204
190
|
geometries: this.#create('geometries', this.#tables.geometry_words.byteLength),
|
|
191
|
+
/*
|
|
192
|
+
One want stamp per lookup word, persistent. The cut dedups a want by exchanging the
|
|
193
|
+
frame's tag into it, so this is never cleared and never read back — where it used to
|
|
194
|
+
be a region of the per-frame feedback transient, cleared and mapped every frame at the
|
|
195
|
+
size of the lookup, which is one word per page of every registered geometry
|
|
196
|
+
(RUNTIME_PLAN_2026_09_14 §2.3).
|
|
197
|
+
*/
|
|
198
|
+
want_stamps: this.#create('want stamps', this.#tables.lookup_words.byteLength),
|
|
205
199
|
};
|
|
206
200
|
|
|
201
|
+
this.#visible_from = new Uint32Array(this.#tables.page_capacity).fill(0xFFFFFFFF);
|
|
202
|
+
|
|
207
203
|
// everything starts absent, and "absent" is a sentinel rather than a zero — the lookup has
|
|
208
204
|
// to reach the device before any cut reads it
|
|
209
205
|
this.#dirty.lookup = [0, this.#tables.lookup_words.length];
|
|
@@ -265,6 +261,14 @@ export class GPUVirtualGeometryPool {
|
|
|
265
261
|
return this.#buffers.geometries;
|
|
266
262
|
}
|
|
267
263
|
|
|
264
|
+
/**
|
|
265
|
+
* The persistent, frame-tagged want stamps, one per lookup word.
|
|
266
|
+
* @returns {GPUBuffer}
|
|
267
|
+
*/
|
|
268
|
+
get buffer_want_stamps() {
|
|
269
|
+
return this.#buffers.want_stamps;
|
|
270
|
+
}
|
|
271
|
+
|
|
268
272
|
/**
|
|
269
273
|
* @returns {VGeoRuntimeTables}
|
|
270
274
|
*/
|
|
@@ -279,12 +283,6 @@ export class GPUVirtualGeometryPool {
|
|
|
279
283
|
return this.#resident_bytes;
|
|
280
284
|
}
|
|
281
285
|
|
|
282
|
-
/**
|
|
283
|
-
* @returns {number}
|
|
284
|
-
*/
|
|
285
|
-
get budget_bytes() {
|
|
286
|
-
return this.#budget_bytes;
|
|
287
|
-
}
|
|
288
286
|
|
|
289
287
|
/**
|
|
290
288
|
* The page size every container registered here is required to have been built at.
|
|
@@ -316,11 +314,21 @@ export class GPUVirtualGeometryPool {
|
|
|
316
314
|
}
|
|
317
315
|
|
|
318
316
|
/**
|
|
319
|
-
*
|
|
317
|
+
* The decoded bytes a resident row was charged for, out of its own slot.
|
|
318
|
+
*
|
|
319
|
+
* @param {number} page_row
|
|
320
320
|
* @returns {number}
|
|
321
321
|
*/
|
|
322
|
-
|
|
323
|
-
return this.#
|
|
322
|
+
bytes_of(page_row) {
|
|
323
|
+
return this.#decoded_bytes_of(page_row);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* @param {number} page_row
|
|
328
|
+
* @returns {number} the container page index a resident row holds
|
|
329
|
+
*/
|
|
330
|
+
page_index_of(page_row) {
|
|
331
|
+
return this.#tables.page_field(page_row, VGEO_PAGE_ROW_OFFSET.PAGE_INDEX);
|
|
324
332
|
}
|
|
325
333
|
|
|
326
334
|
/**
|
|
@@ -330,6 +338,20 @@ export class GPUVirtualGeometryPool {
|
|
|
330
338
|
return this.#frame;
|
|
331
339
|
}
|
|
332
340
|
|
|
341
|
+
/**
|
|
342
|
+
* The frame whose flush publishes this row's current occupant, or `0xFFFFFFFF` for none.
|
|
343
|
+
*
|
|
344
|
+
* @param {number} page_row
|
|
345
|
+
* @returns {number}
|
|
346
|
+
*/
|
|
347
|
+
visible_from(page_row) {
|
|
348
|
+
if (page_row >= this.#visible_from.length) {
|
|
349
|
+
return 0xFFFFFFFF;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return this.#visible_from[page_row];
|
|
353
|
+
}
|
|
354
|
+
|
|
333
355
|
/**
|
|
334
356
|
* One past the highest page row handed out — what sizes the feedback buffer's touch stamps.
|
|
335
357
|
* @returns {number}
|
|
@@ -346,11 +368,13 @@ export class GPUVirtualGeometryPool {
|
|
|
346
368
|
}
|
|
347
369
|
|
|
348
370
|
/**
|
|
349
|
-
* Give a container a geometry row
|
|
371
|
+
* Give a container a geometry row and a block of the lookup, with every page absent.
|
|
350
372
|
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
373
|
+
* Nothing resident, not even the root: which pages are here is `VGeoResidency`'s decision and it
|
|
374
|
+
* installs the root through the same door as every other page, pinned in its own tables. A
|
|
375
|
+
* geometry whose root is not here draws nothing — every traversal is seeded with it, invariant
|
|
376
|
+
* §11.7 puts exactly one root cluster in the file — and the residency throws on a registration
|
|
377
|
+
* that cannot make it resident, rolling this back.
|
|
354
378
|
*
|
|
355
379
|
* This is also the door the page-size guarantee is checked at, because it is the last moment a
|
|
356
380
|
* refusal is still cheap: past it, this container's pages are laid into the tier's storage on
|
|
@@ -381,32 +405,17 @@ export class GPUVirtualGeometryPool {
|
|
|
381
405
|
|
|
382
406
|
this.#mark('geometries', row * VGEO_GEOMETRY_ROW_WORDS, VGEO_GEOMETRY_ROW_WORDS);
|
|
383
407
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
this.#tables.unregister_geometry(row);
|
|
397
|
-
|
|
398
|
-
this.#mark('geometries', row * VGEO_GEOMETRY_ROW_WORDS, VGEO_GEOMETRY_ROW_WORDS);
|
|
399
|
-
|
|
400
|
-
throw new Error(
|
|
401
|
-
`virtual geometry: the root page of this container could not be made resident, so`
|
|
402
|
-
+ ` it would draw nothing and every cut seeded from it would read an absent row.`
|
|
403
|
-
+ ` The tier holds ${this.#tables.page_capacity} slots and`
|
|
404
|
-
+ ` ${this.#tables.resident_page_count} are taken, of a ${this.#budget_bytes}-byte`
|
|
405
|
-
+ ` budget with ${this.#resident_bytes} spent.`
|
|
406
|
-
);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
this.#pinned.add(page_row);
|
|
408
|
+
/*
|
|
409
|
+
The block of NONE the tables just wrote has to reach the device too. The first flush
|
|
410
|
+
uploads the lookup whole, so the first container's block rode along; a container
|
|
411
|
+
registered after that flush was leaving zeros behind, and zero is row 0 — every one of
|
|
412
|
+
its pages resolved to another geometry's root and the cut never wanted anything.
|
|
413
|
+
*/
|
|
414
|
+
this.#mark(
|
|
415
|
+
'lookup',
|
|
416
|
+
this.#tables.geometry_field(row, VGEO_GEOMETRY_ROW_OFFSET.LOOKUP_WORD_OFFSET),
|
|
417
|
+
reader.header.total_pages
|
|
418
|
+
);
|
|
410
419
|
|
|
411
420
|
return row;
|
|
412
421
|
}
|
|
@@ -428,8 +437,15 @@ export class GPUVirtualGeometryPool {
|
|
|
428
437
|
return false;
|
|
429
438
|
}
|
|
430
439
|
|
|
440
|
+
// read before the tables forget the row
|
|
441
|
+
const lookup_offset = this.#tables.geometry_field(
|
|
442
|
+
geometry.row, VGEO_GEOMETRY_ROW_OFFSET.LOOKUP_WORD_OFFSET
|
|
443
|
+
);
|
|
444
|
+
const page_count = this.#tables.geometry_field(
|
|
445
|
+
geometry.row, VGEO_GEOMETRY_ROW_OFFSET.PAGE_COUNT
|
|
446
|
+
);
|
|
447
|
+
|
|
431
448
|
for (const page_row of geometry.rows.values()) {
|
|
432
|
-
this.#pinned.delete(page_row);
|
|
433
449
|
this.#unwatch_batch(page_row);
|
|
434
450
|
|
|
435
451
|
// before the eviction, which zeroes the slot header this number lives in
|
|
@@ -445,14 +461,15 @@ export class GPUVirtualGeometryPool {
|
|
|
445
461
|
|
|
446
462
|
for (const page_row of this.#tables.unregister_geometry(geometry.row)) {
|
|
447
463
|
this.#owner.delete(page_row);
|
|
448
|
-
this.#
|
|
464
|
+
this.#visible_from[page_row] = 0xFFFFFFFF;
|
|
449
465
|
|
|
450
466
|
this.#mark('arena', page_row * this.#tables.slot_words, VGEO_PAGE_ROW_WORDS);
|
|
451
467
|
}
|
|
452
468
|
|
|
453
469
|
this.#geometries.delete(reader);
|
|
454
470
|
|
|
455
|
-
this
|
|
471
|
+
// this geometry's words and not the whole lookup, which is every registered geometry's
|
|
472
|
+
this.#mark('lookup', lookup_offset, page_count);
|
|
456
473
|
this.#mark(
|
|
457
474
|
'geometries', geometry.row * VGEO_GEOMETRY_ROW_WORDS, VGEO_GEOMETRY_ROW_WORDS
|
|
458
475
|
);
|
|
@@ -551,14 +568,11 @@ export class GPUVirtualGeometryPool {
|
|
|
551
568
|
|
|
552
569
|
if (this.#tables.slot_words_for(page) > this.#tables.slot_words) {
|
|
553
570
|
// nothing to evict for: no slot in this tier is ever bigger than another
|
|
554
|
-
this.#refused_install_count++;
|
|
555
|
-
|
|
556
571
|
return -1;
|
|
557
572
|
}
|
|
558
573
|
|
|
559
|
-
if (!this.#
|
|
560
|
-
|
|
561
|
-
|
|
574
|
+
if (!this.#tables.has_free_page_row) {
|
|
575
|
+
// room is the residency's business; a full table here is a refusal, not a cue
|
|
562
576
|
return -1;
|
|
563
577
|
}
|
|
564
578
|
|
|
@@ -571,8 +585,6 @@ export class GPUVirtualGeometryPool {
|
|
|
571
585
|
} catch (error) {
|
|
572
586
|
this.#meshlets.remove_batch(batch);
|
|
573
587
|
|
|
574
|
-
this.#refused_install_count++;
|
|
575
|
-
|
|
576
588
|
return -1;
|
|
577
589
|
}
|
|
578
590
|
|
|
@@ -580,7 +592,8 @@ export class GPUVirtualGeometryPool {
|
|
|
580
592
|
geometry.rows.set(page_index, page_row);
|
|
581
593
|
|
|
582
594
|
this.#owner.set(page_row, geometry);
|
|
583
|
-
this
|
|
595
|
+
// this frame's flush has run; the next one is what publishes this row
|
|
596
|
+
this.#visible_from[page_row] = this.#frame + 1;
|
|
584
597
|
this.#watch_batch(page_row, batch);
|
|
585
598
|
|
|
586
599
|
this.#resident_bytes += page.decoded_size;
|
|
@@ -591,12 +604,10 @@ export class GPUVirtualGeometryPool {
|
|
|
591
604
|
) + page_index, 1);
|
|
592
605
|
this.#mark('geometries', geometry.row * VGEO_GEOMETRY_ROW_WORDS, VGEO_GEOMETRY_ROW_WORDS);
|
|
593
606
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
*/
|
|
599
|
-
this.#refresh_selectable(geometry);
|
|
607
|
+
// activation reaches further than the page that arrived — a group becomes selectable when
|
|
608
|
+
// the last of its parents' pages installs, and the tables cascade that — so the rows whose
|
|
609
|
+
// flags flipped are whatever they say, not this page's alone
|
|
610
|
+
this.#mark_activated();
|
|
600
611
|
|
|
601
612
|
return page_row;
|
|
602
613
|
}
|
|
@@ -606,10 +617,6 @@ export class GPUVirtualGeometryPool {
|
|
|
606
617
|
* @returns {boolean}
|
|
607
618
|
*/
|
|
608
619
|
evict(page_row) {
|
|
609
|
-
if (this.#pinned.has(page_row)) {
|
|
610
|
-
return false;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
620
|
const geometry = this.#owner.get(page_row);
|
|
614
621
|
|
|
615
622
|
if (geometry === undefined) {
|
|
@@ -639,14 +646,14 @@ export class GPUVirtualGeometryPool {
|
|
|
639
646
|
geometry.rows.delete(page_index);
|
|
640
647
|
|
|
641
648
|
this.#owner.delete(page_row);
|
|
642
|
-
this.#
|
|
649
|
+
this.#visible_from[page_row] = 0xFFFFFFFF;
|
|
643
650
|
|
|
644
651
|
this.#evicted_page_count++;
|
|
645
652
|
|
|
646
653
|
this.#mark_slot(page_row);
|
|
647
654
|
this.#mark('lookup', lookup_word, 1);
|
|
648
655
|
|
|
649
|
-
this.#
|
|
656
|
+
this.#mark_activated();
|
|
650
657
|
|
|
651
658
|
return true;
|
|
652
659
|
}
|
|
@@ -671,106 +678,15 @@ export class GPUVirtualGeometryPool {
|
|
|
671
678
|
}
|
|
672
679
|
|
|
673
680
|
/**
|
|
674
|
-
*
|
|
681
|
+
* The runtime calls this at `begin_frame`, before the flush; see {@link visible_from} for why
|
|
682
|
+
* the order matters.
|
|
675
683
|
*
|
|
676
|
-
* @param {number} page_row
|
|
677
|
-
* @returns {void}
|
|
678
|
-
*/
|
|
679
|
-
touch(page_row) {
|
|
680
|
-
if (this.#owner.has(page_row)) {
|
|
681
|
-
this.#touched.set(page_row, this.#frame);
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
/**
|
|
686
684
|
* @returns {void}
|
|
687
685
|
*/
|
|
688
686
|
advance_frame() {
|
|
689
687
|
this.#frame++;
|
|
690
688
|
}
|
|
691
689
|
|
|
692
|
-
/**
|
|
693
|
-
* Whether a page may go: not pinned, not touched inside the protect window, and with no VRAM
|
|
694
|
-
* child.
|
|
695
|
-
*
|
|
696
|
-
* The child rule is this tier's own, out of this tier's tables. Dropping a parent while its
|
|
697
|
-
* children stay leaves those children unreachable — nothing refines into them any more — so
|
|
698
|
-
* they would sit in VRAM, selectable, and never drawn.
|
|
699
|
-
*
|
|
700
|
-
* @param {number} page_row
|
|
701
|
-
* @returns {boolean}
|
|
702
|
-
*/
|
|
703
|
-
evictable(page_row) {
|
|
704
|
-
if (this.#pinned.has(page_row)) {
|
|
705
|
-
return false;
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
if (!this.#owner.has(page_row)) {
|
|
709
|
-
return false;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
if (this.#frame - (this.#touched.get(page_row) ?? 0) < this.#protect_window) {
|
|
713
|
-
return false;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
return !this.#tables.has_resident_child(page_row);
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
/**
|
|
720
|
-
* Drop coldest-first until a slot is free and `bytes` fit.
|
|
721
|
-
*
|
|
722
|
-
* Both budgets bind. Slots are fixed and finite now, so a full table is a reason to evict in its
|
|
723
|
-
* own right — where it used to be a permanent cliff independent of the byte budget
|
|
724
|
-
* (REVIEW_LEDGER M17).
|
|
725
|
-
*
|
|
726
|
-
* @param {number} bytes
|
|
727
|
-
* @returns {boolean}
|
|
728
|
-
*/
|
|
729
|
-
#make_room(bytes) {
|
|
730
|
-
let guard = this.#tables.resident_page_count + 1;
|
|
731
|
-
|
|
732
|
-
while (guard-- > 0) {
|
|
733
|
-
const short = this.#resident_bytes + bytes > this.#budget_bytes
|
|
734
|
-
|| !this.#tables.has_free_page_row;
|
|
735
|
-
|
|
736
|
-
if (!short) {
|
|
737
|
-
return true;
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
const coldest = this.#coldest();
|
|
741
|
-
|
|
742
|
-
if (coldest === -1) {
|
|
743
|
-
// nothing may go — every page is pinned, hot, or a parent. Refusing the install is
|
|
744
|
-
// the right answer: the cut clamps and draws coarser, which is what it is for.
|
|
745
|
-
return false;
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
this.evict(coldest);
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
return this.#resident_bytes + bytes <= this.#budget_bytes
|
|
752
|
-
&& this.#tables.has_free_page_row;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
/**
|
|
756
|
-
* @returns {number} page row, or -1
|
|
757
|
-
*/
|
|
758
|
-
#coldest() {
|
|
759
|
-
let best = -1;
|
|
760
|
-
let best_stamp = Number.POSITIVE_INFINITY;
|
|
761
|
-
|
|
762
|
-
for (const [page_row, stamp] of this.#touched) {
|
|
763
|
-
if (stamp >= best_stamp || !this.evictable(page_row)) {
|
|
764
|
-
continue;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
best = page_row;
|
|
768
|
-
best_stamp = stamp;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
return best;
|
|
772
|
-
}
|
|
773
|
-
|
|
774
690
|
/**
|
|
775
691
|
* @param {number} page_row
|
|
776
692
|
* @returns {number}
|
|
@@ -816,10 +732,10 @@ export class GPUVirtualGeometryPool {
|
|
|
816
732
|
}
|
|
817
733
|
|
|
818
734
|
/**
|
|
819
|
-
*
|
|
735
|
+
* Upload the group rows whose flags the tables flipped.
|
|
820
736
|
*/
|
|
821
|
-
#
|
|
822
|
-
for (const page_row of this.#tables.
|
|
737
|
+
#mark_activated() {
|
|
738
|
+
for (const page_row of this.#tables.take_activated_rows()) {
|
|
823
739
|
const [start, count] = this.#tables.group_range(page_row);
|
|
824
740
|
|
|
825
741
|
this.#mark('arena', start, count);
|