@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
|
@@ -17,6 +17,10 @@ import { vgeo_runtime_page_block_words } from "./vgeo_runtime_page_block_words.j
|
|
|
17
17
|
import { vgeo_runtime_page_slot_words } from "./vgeo_runtime_page_slot_words.js";
|
|
18
18
|
import { vgeo_runtime_write_page_block } from "./vgeo_runtime_write_page_block.js";
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {import("../format/read/VGeoPage.js").VGeoPage} VGeoPage
|
|
22
|
+
*/
|
|
23
|
+
|
|
20
24
|
/**
|
|
21
25
|
* What a VRAM-resident page **is**, with no device anywhere near it.
|
|
22
26
|
*
|
|
@@ -44,10 +48,10 @@ import { vgeo_runtime_write_page_block } from "./vgeo_runtime_write_page_block.j
|
|
|
44
48
|
* row of a second table, which saves the traversal a storage binding it does not have to spare
|
|
45
49
|
* (RUNTIME_PLAN §4.9) and makes an install one contiguous range.
|
|
46
50
|
*
|
|
47
|
-
* ## This tier answers its own activation question
|
|
51
|
+
* ## This tier answers its own activation question, and keeps the answer
|
|
48
52
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
53
|
+
* Selectability is computed from the arena and the lookup — this tier's residency — and consults
|
|
54
|
+
* no reader. It used to publish `VGeoContainerReader.is_selectable`, which
|
|
51
55
|
* is a fact about the **RAM** tier, into the flag the kernel reads while the descent was gated on
|
|
52
56
|
* the **VRAM** lookup. VRAM is a strict subset, so a group could be flagged selectable while a page
|
|
53
57
|
* holding one of its parents had no row here, and the parent's own ancestor then drew a coarse
|
|
@@ -55,6 +59,22 @@ import { vgeo_runtime_write_page_block } from "./vgeo_runtime_write_page_block.j
|
|
|
55
59
|
* the group row carrying its parent count (VGEO_GROUP_ROW_OFFSET.PARENT_COUNT) so that the rule
|
|
56
60
|
* can be evaluated where the residency it is about lives.
|
|
57
61
|
*
|
|
62
|
+
* And it is **kept, not recomputed**. The rule is design §6's: a group is selectable iff every one
|
|
63
|
+
* of its parent-cluster references is live — the referencing cluster's page resident here and
|
|
64
|
+
* that cluster's own group selectable here. `refresh_selectable` used to evaluate that as a
|
|
65
|
+
* closure over every resident group of the geometry after every install and every evict: 4.2 ms
|
|
66
|
+
* a call at 4,096 resident pages of a real asset, twice per promotion at a full tier, which is
|
|
67
|
+
* where a 637 ms frame came from (RUNTIME_PLAN_2026_09_14 §0). §6 also says how it is meant to
|
|
68
|
+
* be kept — "carried by a counter instead of dependency lists … activation cascades" — and
|
|
69
|
+
* `VGeoContainerReader` already does that for the RAM tier. This tier does it over the arena:
|
|
70
|
+
* the live-reference count lives in the group row's FLAGS word above the flag bit, a page's
|
|
71
|
+
* groups are seeded from the resident parents that reference them when it arrives, and the
|
|
72
|
+
* groups that reach their count cascade into the resident children that were waiting on them
|
|
73
|
+
* (§3 of that plan). An install costs the clusters of the page's resident parents plus the
|
|
74
|
+
* cascade; an eviction under the child rule cascades nothing, because nothing resident depends
|
|
75
|
+
* on a page with no resident children. The rule itself survives as the fixpoint oracle
|
|
76
|
+
* `VGeoRuntimeTables.spec.js` holds the counter to after every step of random tours.
|
|
77
|
+
*
|
|
58
78
|
* **Nothing here decides anything.** What to install, what to evict — all of that is the pool's.
|
|
59
79
|
* What this refuses is only what it cannot represent.
|
|
60
80
|
*
|
|
@@ -120,12 +140,39 @@ export class VGeoRuntimeTables {
|
|
|
120
140
|
#resident_rows = new Set();
|
|
121
141
|
|
|
122
142
|
/**
|
|
123
|
-
* Resident page rows per geometry row
|
|
124
|
-
* eviction has to look at to find a page's VRAM children.
|
|
143
|
+
* Resident page rows per geometry row.
|
|
125
144
|
* @type {Map<number, Set<number>>}
|
|
126
145
|
*/
|
|
127
146
|
#geometry_rows = new Map();
|
|
128
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Per geometry row, the reverse index of the DAG over this tier's residency: container page
|
|
150
|
+
* index to the resident page rows whose clusters refer into that page. Written from a page's
|
|
151
|
+
* own child table when it installs and removed when it evicts, so an entry is O(parents) and
|
|
152
|
+
* a lookup is O(1) — design §6's "reverse-reference index", kept for resident pages too. It is
|
|
153
|
+
* what seeds an arriving page's live counts from the parents already here, and what keeps
|
|
154
|
+
* {@link resident_children} without a cluster walk per candidate.
|
|
155
|
+
* @type {Map<number, Map<number, number[]>>}
|
|
156
|
+
*/
|
|
157
|
+
#referrers = new Map();
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Per page row, how many distinct child pages of it are resident in this tier — design §6's
|
|
161
|
+
* eviction rule, "no child page resident in this tier", as a number kept at install and evict
|
|
162
|
+
* rather than a walk of the page's clusters per candidate (REVIEW_LEDGER M9 for why it is this
|
|
163
|
+
* tier's own answer and not the reader's).
|
|
164
|
+
* @type {Uint32Array}
|
|
165
|
+
*/
|
|
166
|
+
#resident_children;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Page rows whose group flags flipped since {@link take_activated_rows} last emptied it — what
|
|
170
|
+
* the owner has to upload. Counts move without appearing here: the kernels mask the flag bit
|
|
171
|
+
* and never read the count, so a count alone is not worth a dirty range.
|
|
172
|
+
* @type {number[]}
|
|
173
|
+
*/
|
|
174
|
+
#activated = [];
|
|
175
|
+
|
|
129
176
|
/**
|
|
130
177
|
* Lookup allocation per geometry row, so an unregistered geometry gives its lookup back.
|
|
131
178
|
* @type {Map<number, Allocation>}
|
|
@@ -196,13 +243,6 @@ export class VGeoRuntimeTables {
|
|
|
196
243
|
*/
|
|
197
244
|
#broken_child_refs = 0;
|
|
198
245
|
|
|
199
|
-
/**
|
|
200
|
-
* Scratch for {@link refresh_selectable}: live parent references per resident group, indexed by
|
|
201
|
-
* the group's word offset in the arena. One map reused across calls rather than one allocated
|
|
202
|
-
* per call, because activation runs on every install and every eviction.
|
|
203
|
-
* @type {Map<number, number>}
|
|
204
|
-
*/
|
|
205
|
-
#live_refs = new Map();
|
|
206
246
|
|
|
207
247
|
/**
|
|
208
248
|
* @param {Object} [options]
|
|
@@ -232,6 +272,7 @@ export class VGeoRuntimeTables {
|
|
|
232
272
|
this.#lookup = new Uint32Array(lookup_words);
|
|
233
273
|
this.#geometries = new Uint32Array(geometry_capacity * VGEO_GEOMETRY_ROW_WORDS);
|
|
234
274
|
this.#generations = new Uint32Array(page_capacity);
|
|
275
|
+
this.#resident_children = new Uint32Array(page_capacity);
|
|
235
276
|
|
|
236
277
|
const words = new Uint32Array(page_capacity * slot_words);
|
|
237
278
|
|
|
@@ -372,6 +413,7 @@ export class VGeoRuntimeTables {
|
|
|
372
413
|
|
|
373
414
|
this.#ordinals.set(row, { free: [], high_water: ordinal_capacity });
|
|
374
415
|
this.#geometry_rows.set(row, new Set());
|
|
416
|
+
this.#referrers.set(row, new Map());
|
|
375
417
|
|
|
376
418
|
return row;
|
|
377
419
|
}
|
|
@@ -399,8 +441,9 @@ export class VGeoRuntimeTables {
|
|
|
399
441
|
const allocation = this.#geometry_allocations.get(geometry_row);
|
|
400
442
|
|
|
401
443
|
if (allocation !== undefined) {
|
|
444
|
+
// absent, not row 0: a freed block is still a block some late reader can name
|
|
402
445
|
this.#lookup.fill(
|
|
403
|
-
|
|
446
|
+
VGEO_PAGE_ROW_NONE,
|
|
404
447
|
allocation.offset,
|
|
405
448
|
allocation.offset + this.geometry_field(
|
|
406
449
|
geometry_row, VGEO_GEOMETRY_ROW_OFFSET.PAGE_COUNT
|
|
@@ -422,6 +465,7 @@ export class VGeoRuntimeTables {
|
|
|
422
465
|
] = VGEO_PAGE_ROW_NONE;
|
|
423
466
|
|
|
424
467
|
this.#geometry_rows.delete(geometry_row);
|
|
468
|
+
this.#referrers.delete(geometry_row);
|
|
425
469
|
this.#ordinals.delete(geometry_row);
|
|
426
470
|
this.#free_geometry_rows.push(geometry_row);
|
|
427
471
|
|
|
@@ -487,12 +531,29 @@ export class VGeoRuntimeTables {
|
|
|
487
531
|
+ this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.GROUP_COUNT) * VGEO_GROUP_ROW_WORDS;
|
|
488
532
|
}
|
|
489
533
|
|
|
534
|
+
/**
|
|
535
|
+
* Word offset of a page's parent rows, which is the end of its cluster rows.
|
|
536
|
+
*
|
|
537
|
+
* Equal to the end of the block when the page has none, which is every page of a container
|
|
538
|
+
* written before `format_version` 4: `PARENT_ENTRY_COUNT` is zero and nothing reads past it.
|
|
539
|
+
*
|
|
540
|
+
* @param {number} page_row
|
|
541
|
+
* @returns {number}
|
|
542
|
+
*/
|
|
543
|
+
parent_base(page_row) {
|
|
544
|
+
return this.cluster_base(page_row)
|
|
545
|
+
+ this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.CLUSTER_COUNT) * VGEO_CLUSTER_ROW_WORDS;
|
|
546
|
+
}
|
|
547
|
+
|
|
490
548
|
/**
|
|
491
549
|
* Make a decoded page resident: one slot, one lookup word.
|
|
492
550
|
*
|
|
493
|
-
* The page
|
|
494
|
-
*
|
|
495
|
-
*
|
|
551
|
+
* The page's rows are written with every group's flag clear, and then activated in place: its
|
|
552
|
+
* groups are seeded with the live references the resident parents make into them, the ones
|
|
553
|
+
* that reach their parent count flip on, and the flip cascades into whatever resident children
|
|
554
|
+
* were waiting on this page. A page that arrives drawing would draw before the ancestors it
|
|
555
|
+
* hangs off have; a page whose arrival completes a group several pages down turns that group
|
|
556
|
+
* on. Both are this method's, and the rows that flipped are on {@link take_activated_rows}.
|
|
496
557
|
*
|
|
497
558
|
* @param {number} geometry_row
|
|
498
559
|
* @param {VGeoPage} page as `vgeo_read_page` decoded it
|
|
@@ -510,8 +571,11 @@ export class VGeoRuntimeTables {
|
|
|
510
571
|
const group_count = page.group_cluster_first.length;
|
|
511
572
|
const cluster_count = page.cluster_count;
|
|
512
573
|
|
|
513
|
-
const
|
|
514
|
-
|
|
574
|
+
const parent_entry_count = page.parent_ref.length;
|
|
575
|
+
|
|
576
|
+
const words = VGEO_PAGE_ROW_WORDS + vgeo_runtime_page_block_words(
|
|
577
|
+
node_count, group_count, cluster_count, parent_entry_count
|
|
578
|
+
);
|
|
515
579
|
|
|
516
580
|
if (words > this.#slot_words) {
|
|
517
581
|
throw new Error(
|
|
@@ -546,6 +610,16 @@ export class VGeoRuntimeTables {
|
|
|
546
610
|
this.#arena[base + VGEO_PAGE_ROW_OFFSET.ORDINAL] = ordinal;
|
|
547
611
|
this.#arena[base + VGEO_PAGE_ROW_OFFSET.GEOMETRY_ROW] = geometry_row;
|
|
548
612
|
this.#arena[base + VGEO_PAGE_ROW_OFFSET.DECODED_SIZE] = page.decoded_size;
|
|
613
|
+
this.#arena[base + VGEO_PAGE_ROW_OFFSET.PARENT_ENTRY_COUNT] = parent_entry_count;
|
|
614
|
+
|
|
615
|
+
/*
|
|
616
|
+
The generation this row is at as it takes this occupant. An eviction bumps it, so anything
|
|
617
|
+
that stores a page row and outlives the frame can tell "still the page I meant" from "that
|
|
618
|
+
slot was refilled" with one equality against the value it saw. It is mirrored here rather
|
|
619
|
+
than read from #generations because the kernel cannot reach a private field, and it is a
|
|
620
|
+
counter rather than a frame number because a row can be refilled twice inside one frame.
|
|
621
|
+
*/
|
|
622
|
+
this.#arena[base + VGEO_PAGE_ROW_OFFSET.GENERATION] = this.#generations[page_row];
|
|
549
623
|
|
|
550
624
|
this.#resident_rows.add(page_row);
|
|
551
625
|
this.#geometry_rows.get(geometry_row).add(page_row);
|
|
@@ -562,6 +636,9 @@ export class VGeoRuntimeTables {
|
|
|
562
636
|
] = page_row;
|
|
563
637
|
}
|
|
564
638
|
|
|
639
|
+
this.#link(page_row, geometry_row, page, lookup_base);
|
|
640
|
+
this.#activate(page_row, geometry_row, page, lookup_base);
|
|
641
|
+
|
|
565
642
|
return page_row;
|
|
566
643
|
}
|
|
567
644
|
|
|
@@ -573,7 +650,8 @@ export class VGeoRuntimeTables {
|
|
|
573
650
|
*/
|
|
574
651
|
slot_words_for(page) {
|
|
575
652
|
return VGEO_PAGE_ROW_WORDS + vgeo_runtime_page_block_words(
|
|
576
|
-
page.node_count, page.group_cluster_first.length, page.cluster_count
|
|
653
|
+
page.node_count, page.group_cluster_first.length, page.cluster_count,
|
|
654
|
+
page.parent_ref.length
|
|
577
655
|
);
|
|
578
656
|
}
|
|
579
657
|
|
|
@@ -614,6 +692,10 @@ export class VGeoRuntimeTables {
|
|
|
614
692
|
|
|
615
693
|
this.#give_ordinal(geometry_row, this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.ORDINAL));
|
|
616
694
|
|
|
695
|
+
// before the header is zeroed: both read this page's rows
|
|
696
|
+
this.#deactivate_page(page_row, lookup_base);
|
|
697
|
+
this.#unlink(page_row, geometry_row, page_index, lookup_base);
|
|
698
|
+
|
|
617
699
|
const base = page_row * this.#slot_words;
|
|
618
700
|
|
|
619
701
|
this.#arena.fill(0, base, base + VGEO_PAGE_ROW_WORDS);
|
|
@@ -639,80 +721,177 @@ export class VGeoRuntimeTables {
|
|
|
639
721
|
}
|
|
640
722
|
|
|
641
723
|
/**
|
|
642
|
-
*
|
|
724
|
+
* How many distinct child pages of this one are resident in this tier.
|
|
643
725
|
*
|
|
644
|
-
* Design §6's eviction rule reads "no child page resident in this tier", and this answers it
|
|
645
|
-
* of
|
|
646
|
-
*
|
|
647
|
-
* (REVIEW_LEDGER M9).
|
|
726
|
+
* Design §6's eviction rule reads "no child page resident in this tier", and this answers it
|
|
727
|
+
* out of a count kept at install and evict rather than a walk of the page's cluster rows per
|
|
728
|
+
* candidate — and out of this tier's own residency rather than the RAM reader's child table,
|
|
729
|
+
* which returned "no children" the moment the RAM tier dropped the page (REVIEW_LEDGER M9).
|
|
648
730
|
*
|
|
649
731
|
* @param {number} page_row
|
|
650
|
-
* @returns {
|
|
732
|
+
* @returns {number}
|
|
651
733
|
*/
|
|
652
|
-
|
|
653
|
-
|
|
734
|
+
resident_children(page_row) {
|
|
735
|
+
return this.#resident_children[page_row];
|
|
736
|
+
}
|
|
654
737
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
738
|
+
/**
|
|
739
|
+
* Page rows whose group flags flipped since this was last called, and empties the list.
|
|
740
|
+
*
|
|
741
|
+
* @returns {number[]}
|
|
742
|
+
*/
|
|
743
|
+
take_activated_rows() {
|
|
744
|
+
const rows = this.#activated;
|
|
745
|
+
|
|
746
|
+
this.#activated = [];
|
|
747
|
+
|
|
748
|
+
return rows;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Put an arriving page into the reverse index and the child counts.
|
|
753
|
+
*
|
|
754
|
+
* Both directions, because a page arrives in either order relative to its parents: a child
|
|
755
|
+
* fetched through one parent while another parent page is absent, and that parent arriving
|
|
756
|
+
* later, are both the ordinary streaming path. So the page counts the children of its own that
|
|
757
|
+
* are already here, and every resident parent that refers into it counts one more.
|
|
758
|
+
*
|
|
759
|
+
* @param {number} page_row
|
|
760
|
+
* @param {number} geometry_row
|
|
761
|
+
* @param {VGeoPage} page
|
|
762
|
+
* @param {number} lookup_base
|
|
763
|
+
*/
|
|
764
|
+
#link(page_row, geometry_row, page, lookup_base) {
|
|
765
|
+
const referrers = this.#referrers.get(geometry_row);
|
|
766
|
+
|
|
767
|
+
// the child table is the distinct list; the cluster rows repeat it once per cluster
|
|
768
|
+
for (const child of page.child_page_index) {
|
|
769
|
+
let rows = referrers.get(child);
|
|
770
|
+
|
|
771
|
+
if (rows === undefined) {
|
|
772
|
+
rows = [];
|
|
773
|
+
|
|
774
|
+
referrers.set(child, rows);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
rows.push(page_row);
|
|
778
|
+
|
|
779
|
+
if (this.#lookup[lookup_base + child] !== VGEO_PAGE_ROW_NONE) {
|
|
780
|
+
this.#resident_children[page_row]++;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
const parents = referrers.get(page.index);
|
|
658
785
|
|
|
786
|
+
if (parents !== undefined) {
|
|
787
|
+
for (const parent_row of parents) {
|
|
788
|
+
this.#resident_children[parent_row]++;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* Take a leaving page out of the reverse index and the child counts.
|
|
795
|
+
*
|
|
796
|
+
* @param {number} page_row
|
|
797
|
+
* @param {number} geometry_row
|
|
798
|
+
* @param {number} page_index
|
|
799
|
+
* @param {number} lookup_base
|
|
800
|
+
*/
|
|
801
|
+
#unlink(page_row, geometry_row, page_index, lookup_base) {
|
|
802
|
+
const referrers = this.#referrers.get(geometry_row);
|
|
803
|
+
|
|
804
|
+
// out of every child's list of parents; the rows repeat a child once per cluster, and the
|
|
805
|
+
// list holds this row once, so only the first cluster naming a child finds anything
|
|
659
806
|
const cluster_count = this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.CLUSTER_COUNT);
|
|
660
807
|
const cluster_base = this.cluster_base(page_row);
|
|
661
808
|
|
|
662
809
|
for (let cluster = 0; cluster < cluster_count; cluster++) {
|
|
663
|
-
const
|
|
810
|
+
const child = this.#arena[
|
|
664
811
|
cluster_base + cluster * VGEO_CLUSTER_ROW_WORDS
|
|
665
812
|
+ VGEO_CLUSTER_ROW_OFFSET.CHILD_PAGE_INDEX
|
|
666
813
|
];
|
|
667
814
|
|
|
668
|
-
if (
|
|
815
|
+
if (child === VGEO_NO_CHILD_PAGE || child === page_index) {
|
|
669
816
|
continue;
|
|
670
817
|
}
|
|
671
818
|
|
|
672
|
-
const
|
|
819
|
+
const rows = referrers.get(child);
|
|
673
820
|
|
|
674
|
-
if (
|
|
675
|
-
|
|
821
|
+
if (rows === undefined) {
|
|
822
|
+
continue;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
const at = rows.indexOf(page_row);
|
|
826
|
+
|
|
827
|
+
if (at !== -1) {
|
|
828
|
+
rows.splice(at, 1);
|
|
829
|
+
|
|
830
|
+
if (rows.length === 0) {
|
|
831
|
+
referrers.delete(child);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
const parents = referrers.get(page_index);
|
|
837
|
+
|
|
838
|
+
if (parents !== undefined) {
|
|
839
|
+
for (const parent_row of parents) {
|
|
840
|
+
this.#resident_children[parent_row]--;
|
|
676
841
|
}
|
|
677
842
|
}
|
|
678
843
|
|
|
679
|
-
|
|
844
|
+
this.#resident_children[page_row] = 0;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* @param {number} group_row word offset of a group row
|
|
849
|
+
* @returns {number} live parent references counted so far
|
|
850
|
+
*/
|
|
851
|
+
#live_count(group_row) {
|
|
852
|
+
return this.#arena[group_row + VGEO_GROUP_ROW_OFFSET.FLAGS] >>> 16;
|
|
680
853
|
}
|
|
681
854
|
|
|
682
855
|
/**
|
|
683
|
-
*
|
|
856
|
+
* One more live reference into a group. Above the flag bit, which the kernels mask; a count
|
|
857
|
+
* alone marks nothing dirty.
|
|
684
858
|
*
|
|
685
|
-
*
|
|
686
|
-
*
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
859
|
+
* @param {number} group_row
|
|
860
|
+
* @returns {boolean} whether the count now equals the group's parent count
|
|
861
|
+
*/
|
|
862
|
+
#count_reference(group_row) {
|
|
863
|
+
const word = group_row + VGEO_GROUP_ROW_OFFSET.FLAGS;
|
|
864
|
+
|
|
865
|
+
this.#arena[word] += 1 << 16;
|
|
866
|
+
|
|
867
|
+
return (this.#arena[word] >>> 16) === this.#arena[group_row + VGEO_GROUP_ROW_OFFSET.PARENT_COUNT];
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Activate an arriving page: seed its groups from the resident parents that refer into them,
|
|
872
|
+
* then cascade from every group that has all of its parents.
|
|
691
873
|
*
|
|
692
|
-
*
|
|
693
|
-
*
|
|
694
|
-
* order as the install that provoked it — one pass over the geometry's resident clusters. The
|
|
695
|
-
* incremental form is a later optimization with a counter to keep correct; the one thing it
|
|
696
|
-
* must not be is a *second* implementation of the rule.
|
|
874
|
+
* Same-page parents are not seeded; the cascade reaches them, because the page's own lookup
|
|
875
|
+
* word is already set and a same-page child reference resolves to this row.
|
|
697
876
|
*
|
|
877
|
+
* @param {number} page_row
|
|
698
878
|
* @param {number} geometry_row
|
|
699
|
-
* @
|
|
879
|
+
* @param {VGeoPage} page
|
|
880
|
+
* @param {number} lookup_base
|
|
700
881
|
*/
|
|
701
|
-
|
|
702
|
-
const rows = this.#geometry_rows.get(geometry_row);
|
|
703
|
-
|
|
704
|
-
if (rows === undefined || rows.size === 0) {
|
|
705
|
-
return [];
|
|
706
|
-
}
|
|
707
|
-
|
|
882
|
+
#activate(page_row, geometry_row, page, lookup_base) {
|
|
708
883
|
const arena = this.#arena;
|
|
709
|
-
const live = this.#live_refs;
|
|
710
884
|
|
|
711
|
-
|
|
885
|
+
const group_count = page.group_cluster_first.length;
|
|
886
|
+
const group_base = this.group_base(page_row);
|
|
712
887
|
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
)
|
|
888
|
+
const parents = this.#referrers.get(geometry_row).get(page.index);
|
|
889
|
+
|
|
890
|
+
if (parents !== undefined) {
|
|
891
|
+
for (const parent_row of parents) {
|
|
892
|
+
this.#seed_from(parent_row, page.index, group_base, group_count);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
716
895
|
|
|
717
896
|
/**
|
|
718
897
|
* Word offsets of group rows to turn on, as a stack.
|
|
@@ -720,37 +899,87 @@ export class VGeoRuntimeTables {
|
|
|
720
899
|
*/
|
|
721
900
|
const queue = [];
|
|
722
901
|
|
|
723
|
-
for (
|
|
724
|
-
const
|
|
725
|
-
const group_base = this.group_base(page_row);
|
|
902
|
+
for (let group = 0; group < group_count; group++) {
|
|
903
|
+
const row = group_base + group * VGEO_GROUP_ROW_WORDS;
|
|
726
904
|
|
|
727
|
-
|
|
728
|
-
|
|
905
|
+
if (this.#live_count(row) === arena[row + VGEO_GROUP_ROW_OFFSET.PARENT_COUNT]) {
|
|
906
|
+
queue.push(row);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
729
909
|
|
|
730
|
-
|
|
910
|
+
this.#cascade(queue, lookup_base);
|
|
911
|
+
}
|
|
731
912
|
|
|
732
|
-
|
|
733
|
-
|
|
913
|
+
/**
|
|
914
|
+
* Count the references one resident parent page's **selectable** groups make into an arriving
|
|
915
|
+
* page's groups.
|
|
916
|
+
*
|
|
917
|
+
* @param {number} parent_row
|
|
918
|
+
* @param {number} child_page_index
|
|
919
|
+
* @param {number} child_group_base
|
|
920
|
+
* @param {number} child_group_count
|
|
921
|
+
*/
|
|
922
|
+
#seed_from(parent_row, child_page_index, child_group_base, child_group_count) {
|
|
923
|
+
const arena = this.#arena;
|
|
924
|
+
|
|
925
|
+
const group_count = this.page_field(parent_row, VGEO_PAGE_ROW_OFFSET.GROUP_COUNT);
|
|
926
|
+
const group_base = this.group_base(parent_row);
|
|
927
|
+
const cluster_base = this.cluster_base(parent_row);
|
|
928
|
+
|
|
929
|
+
for (let group = 0; group < group_count; group++) {
|
|
930
|
+
const group_row = group_base + group * VGEO_GROUP_ROW_WORDS;
|
|
931
|
+
|
|
932
|
+
if ((arena[group_row + VGEO_GROUP_ROW_OFFSET.FLAGS] & VGEO_GROUP_FLAG_SELECTABLE) === 0) {
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
const first = arena[group_row + VGEO_GROUP_ROW_OFFSET.CLUSTER_FIRST];
|
|
937
|
+
const count = arena[group_row + VGEO_GROUP_ROW_OFFSET.CLUSTER_COUNT];
|
|
938
|
+
|
|
939
|
+
for (let i = 0; i < count; i++) {
|
|
940
|
+
const cluster = cluster_base + (first + i) * VGEO_CLUSTER_ROW_WORDS;
|
|
941
|
+
|
|
942
|
+
if (arena[cluster + VGEO_CLUSTER_ROW_OFFSET.CHILD_PAGE_INDEX] !== child_page_index) {
|
|
943
|
+
continue;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
const child_group = arena[cluster + VGEO_CLUSTER_ROW_OFFSET.CHILD_GROUP];
|
|
947
|
+
|
|
948
|
+
if (child_group >= child_group_count) {
|
|
949
|
+
// outside the child page's table; counting it would land in a cluster row
|
|
950
|
+
continue;
|
|
734
951
|
}
|
|
952
|
+
|
|
953
|
+
this.#count_reference(child_group_base + child_group * VGEO_GROUP_ROW_WORDS);
|
|
735
954
|
}
|
|
736
955
|
}
|
|
956
|
+
}
|
|
737
957
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
958
|
+
/**
|
|
959
|
+
* Turn groups on and let each one count itself into its resident children, turning on the
|
|
960
|
+
* children that reach their parent count — design §6's cascade, over this tier's residency.
|
|
961
|
+
*
|
|
962
|
+
* @param {number[]} queue word offsets of group rows whose count has reached their parent count
|
|
963
|
+
* @param {number} lookup_base
|
|
964
|
+
*/
|
|
965
|
+
#cascade(queue, lookup_base) {
|
|
966
|
+
const arena = this.#arena;
|
|
742
967
|
|
|
743
968
|
while (queue.length > 0) {
|
|
744
969
|
const group_row = queue.pop();
|
|
745
970
|
|
|
746
|
-
|
|
971
|
+
const flags_word = group_row + VGEO_GROUP_ROW_OFFSET.FLAGS;
|
|
972
|
+
|
|
973
|
+
if ((arena[flags_word] & VGEO_GROUP_FLAG_SELECTABLE) !== 0) {
|
|
747
974
|
continue;
|
|
748
975
|
}
|
|
749
976
|
|
|
750
|
-
|
|
977
|
+
arena[flags_word] |= VGEO_GROUP_FLAG_SELECTABLE;
|
|
751
978
|
|
|
752
979
|
const page_row = Math.floor(group_row / this.#slot_words);
|
|
753
980
|
|
|
981
|
+
this.#activated.push(page_row);
|
|
982
|
+
|
|
754
983
|
const cluster_base = this.cluster_base(page_row);
|
|
755
984
|
|
|
756
985
|
const first = arena[group_row + VGEO_GROUP_ROW_OFFSET.CLUSTER_FIRST];
|
|
@@ -759,80 +988,131 @@ export class VGeoRuntimeTables {
|
|
|
759
988
|
for (let i = 0; i < count; i++) {
|
|
760
989
|
const cluster = cluster_base + (first + i) * VGEO_CLUSTER_ROW_WORDS;
|
|
761
990
|
|
|
762
|
-
const
|
|
763
|
-
cluster + VGEO_CLUSTER_ROW_OFFSET.CHILD_PAGE_INDEX
|
|
764
|
-
];
|
|
991
|
+
const child = this.#child_group_row(cluster, lookup_base);
|
|
765
992
|
|
|
766
|
-
if (
|
|
993
|
+
if (child === -1) {
|
|
767
994
|
continue;
|
|
768
995
|
}
|
|
769
996
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
if (child_row === VGEO_PAGE_ROW_NONE) {
|
|
773
|
-
// the child page is not in this tier; its groups stay blocked, which is exactly
|
|
774
|
-
// what makes the cluster above clamp and draw
|
|
775
|
-
continue;
|
|
997
|
+
if (this.#count_reference(child)) {
|
|
998
|
+
queue.push(child);
|
|
776
999
|
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
777
1003
|
|
|
778
|
-
|
|
1004
|
+
/**
|
|
1005
|
+
* The group row a cluster refines into, if that group's page is resident and the reference is
|
|
1006
|
+
* inside its table.
|
|
1007
|
+
*
|
|
1008
|
+
* @param {number} cluster word offset of the cluster row
|
|
1009
|
+
* @param {number} lookup_base
|
|
1010
|
+
* @returns {number} word offset of the child group row, or -1
|
|
1011
|
+
*/
|
|
1012
|
+
#child_group_row(cluster, lookup_base) {
|
|
1013
|
+
const arena = this.#arena;
|
|
779
1014
|
|
|
780
|
-
|
|
781
|
-
// a child_group outside the child page's table; counting it would corrupt a
|
|
782
|
-
// neighbour's counter, and the traversal draws the referring cluster instead
|
|
783
|
-
continue;
|
|
784
|
-
}
|
|
1015
|
+
const child_page_index = arena[cluster + VGEO_CLUSTER_ROW_OFFSET.CHILD_PAGE_INDEX];
|
|
785
1016
|
|
|
786
|
-
|
|
1017
|
+
if (child_page_index === VGEO_NO_CHILD_PAGE) {
|
|
1018
|
+
return -1;
|
|
1019
|
+
}
|
|
787
1020
|
|
|
788
|
-
|
|
1021
|
+
const child_row = this.#lookup[lookup_base + child_page_index];
|
|
789
1022
|
|
|
790
|
-
|
|
1023
|
+
if (child_row === VGEO_PAGE_ROW_NONE) {
|
|
1024
|
+
// the child page is not in this tier; its groups stay blocked, which is exactly what
|
|
1025
|
+
// makes the cluster above clamp and draw
|
|
1026
|
+
return -1;
|
|
1027
|
+
}
|
|
791
1028
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
1029
|
+
const child_group = arena[cluster + VGEO_CLUSTER_ROW_OFFSET.CHILD_GROUP];
|
|
1030
|
+
|
|
1031
|
+
if (child_group >= this.page_field(child_row, VGEO_PAGE_ROW_OFFSET.GROUP_COUNT)) {
|
|
1032
|
+
// a child_group outside the child page's table; counting it would corrupt a
|
|
1033
|
+
// neighbour's row, and the traversal draws the referring cluster instead
|
|
1034
|
+
return -1;
|
|
796
1035
|
}
|
|
797
1036
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
1037
|
+
return this.group_base(child_row) + child_group * VGEO_GROUP_ROW_WORDS;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/**
|
|
1041
|
+
* Retract a leaving page's references and turn off whatever they were holding up.
|
|
1042
|
+
*
|
|
1043
|
+
* Under the child rule this finds nothing to retract: a page with no resident child has no
|
|
1044
|
+
* resident group depending on it. It is here for the callers that evict against the rule —
|
|
1045
|
+
* `unregister_geometry`, a tool, a spec — so that a child group is never left selectable
|
|
1046
|
+
* with a parent's page gone, which is the double-draw the whole rule exists to prevent
|
|
1047
|
+
* (REVIEW_LEDGER C1).
|
|
1048
|
+
*
|
|
1049
|
+
* @param {number} page_row
|
|
1050
|
+
* @param {number} lookup_base
|
|
1051
|
+
*/
|
|
1052
|
+
#deactivate_page(page_row, lookup_base) {
|
|
1053
|
+
if (this.#resident_children[page_row] === 0) {
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
802
1056
|
|
|
803
|
-
|
|
804
|
-
const group_count = this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.GROUP_COUNT);
|
|
805
|
-
const group_base = this.group_base(page_row);
|
|
1057
|
+
const arena = this.#arena;
|
|
806
1058
|
|
|
807
|
-
|
|
1059
|
+
const group_count = this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.GROUP_COUNT);
|
|
1060
|
+
const group_base = this.group_base(page_row);
|
|
808
1061
|
|
|
809
|
-
|
|
810
|
-
|
|
1062
|
+
for (let group = 0; group < group_count; group++) {
|
|
1063
|
+
const group_row = group_base + group * VGEO_GROUP_ROW_WORDS;
|
|
811
1064
|
|
|
812
|
-
|
|
1065
|
+
if ((arena[group_row + VGEO_GROUP_ROW_OFFSET.FLAGS] & VGEO_GROUP_FLAG_SELECTABLE) !== 0) {
|
|
1066
|
+
this.#retract(group_row, lookup_base);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
813
1070
|
|
|
814
|
-
|
|
815
|
-
|
|
1071
|
+
/**
|
|
1072
|
+
* Take one selectable group's references back out of its resident children, and turn off —
|
|
1073
|
+
* recursively — every child group that loses one.
|
|
1074
|
+
*
|
|
1075
|
+
* @param {number} group_row
|
|
1076
|
+
* @param {number} lookup_base
|
|
1077
|
+
*/
|
|
1078
|
+
#retract(group_row, lookup_base) {
|
|
1079
|
+
const arena = this.#arena;
|
|
816
1080
|
|
|
817
|
-
|
|
818
|
-
|
|
1081
|
+
const page_row = Math.floor(group_row / this.#slot_words);
|
|
1082
|
+
const cluster_base = this.cluster_base(page_row);
|
|
1083
|
+
|
|
1084
|
+
const first = arena[group_row + VGEO_GROUP_ROW_OFFSET.CLUSTER_FIRST];
|
|
1085
|
+
const count = arena[group_row + VGEO_GROUP_ROW_OFFSET.CLUSTER_COUNT];
|
|
1086
|
+
|
|
1087
|
+
for (let i = 0; i < count; i++) {
|
|
1088
|
+
const cluster = cluster_base + (first + i) * VGEO_CLUSTER_ROW_WORDS;
|
|
1089
|
+
|
|
1090
|
+
const child = this.#child_group_row(cluster, lookup_base);
|
|
1091
|
+
|
|
1092
|
+
if (child === -1) {
|
|
1093
|
+
continue;
|
|
819
1094
|
}
|
|
820
1095
|
|
|
821
|
-
|
|
822
|
-
|
|
1096
|
+
const flags_word = child + VGEO_GROUP_ROW_OFFSET.FLAGS;
|
|
1097
|
+
|
|
1098
|
+
arena[flags_word] -= 1 << 16;
|
|
1099
|
+
|
|
1100
|
+
if ((arena[flags_word] & VGEO_GROUP_FLAG_SELECTABLE) !== 0) {
|
|
1101
|
+
arena[flags_word] &= ~VGEO_GROUP_FLAG_SELECTABLE;
|
|
1102
|
+
|
|
1103
|
+
this.#activated.push(Math.floor(child / this.#slot_words));
|
|
1104
|
+
|
|
1105
|
+
this.#retract(child, lookup_base);
|
|
823
1106
|
}
|
|
824
1107
|
}
|
|
825
|
-
|
|
826
|
-
return changed;
|
|
827
1108
|
}
|
|
828
|
-
|
|
829
1109
|
/**
|
|
830
1110
|
* Publish one group's selectability directly.
|
|
831
1111
|
*
|
|
832
|
-
*
|
|
833
|
-
*
|
|
834
|
-
*
|
|
835
|
-
*
|
|
1112
|
+
* Activation is the tables' own; this is for a spec that needs a state the rule happens not to
|
|
1113
|
+
* produce on the assets measured so far — the cut's own-group term is correctness for exactly
|
|
1114
|
+
* such a state, and a guard nothing can construct is a guard nothing can test. It writes the
|
|
1115
|
+
* flag bit and leaves the count, so the next cascade through the group may overwrite it.
|
|
836
1116
|
*
|
|
837
1117
|
* @param {number} page_row
|
|
838
1118
|
* @param {number} group
|
|
@@ -844,7 +1124,9 @@ export class VGeoRuntimeTables {
|
|
|
844
1124
|
+ group * VGEO_GROUP_ROW_WORDS
|
|
845
1125
|
+ VGEO_GROUP_ROW_OFFSET.FLAGS;
|
|
846
1126
|
|
|
847
|
-
this.#arena[word] = selectable
|
|
1127
|
+
this.#arena[word] = selectable
|
|
1128
|
+
? this.#arena[word] | VGEO_GROUP_FLAG_SELECTABLE
|
|
1129
|
+
: this.#arena[word] & ~VGEO_GROUP_FLAG_SELECTABLE;
|
|
848
1130
|
}
|
|
849
1131
|
|
|
850
1132
|
/**
|
|
@@ -872,7 +1154,8 @@ export class VGeoRuntimeTables {
|
|
|
872
1154
|
const words = VGEO_PAGE_ROW_WORDS + vgeo_runtime_page_block_words(
|
|
873
1155
|
this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.NODE_COUNT),
|
|
874
1156
|
this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.GROUP_COUNT),
|
|
875
|
-
this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.CLUSTER_COUNT)
|
|
1157
|
+
this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.CLUSTER_COUNT),
|
|
1158
|
+
this.page_field(page_row, VGEO_PAGE_ROW_OFFSET.PARENT_ENTRY_COUNT)
|
|
876
1159
|
);
|
|
877
1160
|
|
|
878
1161
|
return [base, words];
|