@woosh/meep-engine 3.27.0 → 3.28.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/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/core/geom/3d/mat4/m4_linear_determinant.d.ts +15 -0
- package/src/core/geom/3d/mat4/m4_linear_determinant.d.ts.map +1 -0
- package/src/core/geom/3d/mat4/m4_linear_determinant.js +24 -0
- package/src/core/geom/3d/mat4/m4_normal_matrix3.d.ts +4 -2
- package/src/core/geom/3d/mat4/m4_normal_matrix3.d.ts.map +1 -1
- package/src/core/geom/3d/mat4/m4_normal_matrix3.js +21 -11
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +38 -1
- package/src/engine/graphics3/GraphicsEngine.d.ts +5 -1
- package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -1
- package/src/engine/graphics3/GraphicsEngine.js +834 -830
- package/src/shade/RENDERER_CONTRACT.md +19 -10
- package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +1 -1
- package/src/shade/playground/vgeo_runtime/README.md +27 -13
- package/src/shade/playground/vgeo_runtime/main.js +18 -5
- package/src/shade/playground/vgeo_runtime/sample_asset.d.ts +18 -0
- package/src/shade/playground/vgeo_runtime/sample_asset.d.ts.map +1 -0
- package/src/shade/playground/{vgeo_viewer → vgeo_runtime}/sample_asset.js +9 -8
- package/src/shade/playground/vgeo_scene/README.md +408 -0
- package/src/shade/playground/vgeo_scene/index.html +144 -0
- package/src/shade/playground/vgeo_scene/main.d.ts +2 -0
- package/src/shade/playground/vgeo_scene/main.d.ts.map +1 -0
- package/src/shade/playground/vgeo_scene/main.js +1716 -0
- package/src/shade/renderer/Renderer.d.ts +4 -1
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +5 -2
- package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +1 -2
- package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/MeshletBatch.js +3 -29
- package/src/shade/renderer/geometry/meshlet/encoding/ENCODED_ATTRIBUTE_DEFAULT_VALUES.d.ts +22 -0
- package/src/shade/renderer/geometry/meshlet/encoding/ENCODED_ATTRIBUTE_DEFAULT_VALUES.d.ts.map +1 -0
- package/src/shade/renderer/geometry/meshlet/encoding/ENCODED_ATTRIBUTE_DEFAULT_VALUES.js +49 -0
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +4 -2
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +10 -8
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +12 -11
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +1 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +1 -1
- package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +5 -9
- package/src/shade/renderer/geometry/virtual/build/level/VGeoLevel.d.ts +32 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoLevel.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts +59 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelSummary.d.ts +44 -0
- package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelSummary.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts +36 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_build_levels.js → level/vgeo_build_levels.js} +61 -95
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_root_group.d.ts +19 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_root_group.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_build_root_group.js → level/vgeo_build_root_group.js} +1 -1
- package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts +73 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{VirtualGeometryMesh.js → mesh/VirtualGeometryMesh.js} +7 -7
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts +29 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_compute_vertex_normals.js → mesh/vgeo_compute_vertex_normals.js} +3 -3
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts +31 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_compute_vertex_tangents.js → mesh/vgeo_compute_vertex_tangents.js} +5 -5
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts +46 -0
- package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_normalize_source.js → mesh/vgeo_normalize_source.js} +9 -9
- package/src/shade/renderer/geometry/virtual/build/page/vgeo_assemble_pages.d.ts +13 -0
- package/src/shade/renderer/geometry/virtual/build/page/vgeo_assemble_pages.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_assemble_pages.js → page/vgeo_assemble_pages.js} +9 -9
- package/src/shade/renderer/geometry/virtual/build/page/vgeo_build_page_nodes.d.ts +13 -0
- package/src/shade/renderer/geometry/virtual/build/page/vgeo_build_page_nodes.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_build_page_nodes.js → page/vgeo_build_page_nodes.js} +4 -4
- package/src/shade/renderer/geometry/virtual/build/page/vgeo_page_node_count.d.ts +22 -0
- package/src/shade/renderer/geometry/virtual/build/page/vgeo_page_node_count.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_page_node_count.js → page/vgeo_page_node_count.js} +2 -2
- package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts +52 -0
- package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{VGeoFaceGraph.js → partition/VGeoFaceGraph.js} +1 -1
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_graph.d.ts +29 -0
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_graph.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_partition_graph.js → partition/vgeo_partition_graph.js} +2 -2
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_subgraph.d.ts +41 -0
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_subgraph.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_subgraph.js +92 -0
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set.d.ts +10 -0
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_split_face_set.js → partition/vgeo_split_face_set.js} +12 -55
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_split_face_set_packed.js → partition/vgeo_split_face_set_packed.js} +3 -3
- package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_bounding_sphere.d.ts +12 -0
- package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_bounding_sphere.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_bounding_sphere.js → sphere/vgeo_bounding_sphere.js} +3 -3
- package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_containing_sphere.d.ts +18 -0
- package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_containing_sphere.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_containing_sphere.js → sphere/vgeo_containing_sphere.js} +3 -3
- package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_sphere_inflate_to_contain.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_sphere_inflate_to_contain.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_sphere_inflate_to_contain.js → sphere/vgeo_sphere_inflate_to_contain.js} +1 -1
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts +24 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts +20 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_extract_submesh.js → submesh/vgeo_extract_submesh.js} +5 -5
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts +12 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_gather_faces.js → submesh/vgeo_gather_faces.js} +2 -2
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_narrow_indices.d.ts +11 -0
- package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_narrow_indices.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/{vgeo_narrow_indices.js → submesh/vgeo_narrow_indices.js} +3 -3
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +9 -11
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.d.ts +8 -2
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +8 -2
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_OFFSET.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_OFFSET.js +15 -0
- package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts +28 -0
- package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +7 -3
- 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 +9 -4
- 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 +18 -5
- 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 +9 -1
- package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +21 -2
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +52 -2
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +97 -1
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +4 -4
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +10 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js +59 -34
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +8 -8
- 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 +11 -88
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.d.ts +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.js +98 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.d.ts +31 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.js +99 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_queue.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_queue.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_queue.js +39 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.js +7 -63
- 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 +13 -30
- 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 +6 -52
- package/src/shade/renderer/loader/gltf/load_gltf.d.ts.map +1 -1
- package/src/shade/renderer/loader/gltf/load_gltf.js +0 -19
- package/src/shade/renderer/material/chunk_material_draw_side.d.ts +14 -0
- package/src/shade/renderer/material/chunk_material_draw_side.d.ts.map +1 -0
- package/src/shade/renderer/material/chunk_material_draw_side.js +34 -0
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer.js +8 -1
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +13 -1
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts +19 -5
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +23 -5
- package/src/shade/renderer/rasterize/bucket/filter_materials_by_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/filter_materials_by_bucket.js +12 -5
- package/src/shade/renderer/rasterize/bucket/rasterization_opaque_buckets.d.ts +22 -0
- package/src/shade/renderer/rasterize/bucket/rasterization_opaque_buckets.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/bucket/rasterization_opaque_buckets.js +36 -0
- package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts +15 -0
- package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.js +35 -0
- package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.d.ts +10 -1
- package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.js +38 -29
- package/src/shade/renderer/rasterize/expand/bucket/chunk_rasterization_material_bucket.d.ts +5 -0
- package/src/shade/renderer/rasterize/expand/bucket/chunk_rasterization_material_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/chunk_rasterization_material_bucket.js +63 -55
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.js +1 -0
- package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +44 -53
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.js +6 -2
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.js +6 -2
- package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.js +19 -2
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +7 -4
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +3 -2
- package/src/shade/renderer/rasterize/native/chunk_rasterize_triangle.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/chunk_rasterize_triangle.js +15 -4
- package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_alpha_tested_pass_descriptor.js +16 -5
- package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_pass_descriptor.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_pass_descriptor.js +16 -5
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +2 -1
- package/src/shade/renderer/rasterize/native/rasterization_shader_resources.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/rasterization_shader_resources.js +4 -0
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +16 -7
- 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 +78 -88
- 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 +21 -31
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +2 -0
- package/src/shade/renderer/scene/NODE3D_STRUCT.d.ts +19 -0
- package/src/shade/renderer/scene/NODE3D_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/scene/NODE3D_STRUCT.js +34 -0
- package/src/shade/renderer/scene/chunk_node3d_flags.d.ts +9 -0
- package/src/shade/renderer/scene/chunk_node3d_flags.d.ts.map +1 -0
- package/src/shade/renderer/scene/chunk_node3d_flags.js +23 -0
- package/src/shade/renderer/scene/chunk_scene_database_access.d.ts.map +1 -1
- package/src/shade/renderer/scene/chunk_scene_database_access.js +15 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.js +9 -1
- package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.d.ts +7 -0
- package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.js +16 -4
- package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.d.ts +12 -0
- package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.js +18 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_triangle_list_reverse_winding.d.ts +24 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_triangle_list_reverse_winding.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_triangle_list_reverse_winding.js +33 -0
- package/src/shade/playground/vgeo_viewer/README.md +0 -150
- package/src/shade/playground/vgeo_viewer/cut_geometry.js +0 -460
- package/src/shade/playground/vgeo_viewer/index.html +0 -77
- package/src/shade/playground/vgeo_viewer/main.js +0 -1343
- package/src/shade/playground/vgeo_viewer/select_cut.js +0 -481
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts +0 -258
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts +0 -49
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/fix_up_material_sides.js +0 -109
- package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.js +0 -78
- package/src/shade/renderer/rasterize/expand/shader_filter_triangle_by_material_side.js +0 -100
- package/src/shade/renderer/rasterize/forward/chunk_material_side_should_draw.js +0 -26
- package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.d.ts +0 -3
- package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.d.ts.map +0 -1
- /package/src/shade/renderer/geometry/virtual/build/{VGeoLevel.js → level/VGeoLevel.js} +0 -0
- /package/src/shade/renderer/geometry/virtual/build/{VGeoLevelOptions.js → level/VGeoLevelOptions.js} +0 -0
- /package/src/shade/renderer/geometry/virtual/build/{VGeoLevelSummary.js → level/VGeoLevelSummary.js} +0 -0
- /package/src/shade/renderer/geometry/virtual/build/{vgeo_graph_components.js → partition/vgeo_graph_components.js} +0 -0
- /package/src/shade/renderer/geometry/virtual/build/{VGeoGatheredFaces.js → submesh/VGeoGatheredFaces.js} +0 -0
- /package/src/shade/renderer/geometry/virtual/build/{VGeoSubmesh.js → submesh/VGeoSubmesh.js} +0 -0
|
@@ -39,7 +39,7 @@ held to `vgeo_select_cut` exactly, and `playground/vgeo_runtime/` runs it on a d
|
|
|
39
39
|
|
|
40
40
|
Everything below the runtime was already built when this was written. The builder produces a DAG,
|
|
41
41
|
the container holds it, the reader streams it a page at a time with residency and activation,
|
|
42
|
-
`VGeoResidencyManager` owns the RAM budget, and `
|
|
42
|
+
`VGeoResidencyManager` owns the RAM budget, and `runtime/cut/__fixtures__/vgeo_select_cut.js` selects a
|
|
43
43
|
correct cut on the CPU against a partially resident container. What had never run was any of it on
|
|
44
44
|
the GPU, and the one piece of M0 that is engine-facing — the expansion seam — had never been built
|
|
45
45
|
at all.
|
|
@@ -76,7 +76,7 @@ no cluster the flat rule would draw is missed.
|
|
|
76
76
|
| `GPUMeshletManager` | data + metadata pools, `add_batch`/`remove_batch` | the VRAM tier's storage; format §8 makes a page payload a **copy** into the data pool |
|
|
77
77
|
| `MESHLET_DEFINITION_STRUCT` | `(meshlet index, mesh index)` | the cut's output record type — unchanged, which is what makes the seam one call |
|
|
78
78
|
| `graph_expand_meshes_to_meshlets` | four call sites, three of them opaque | the seam: a VG expansion runs beside each opaque one and appends into the same collection (§5) |
|
|
79
|
-
| `
|
|
79
|
+
| `cut/__fixtures__/vgeo_select_cut.js` | the rule on the CPU | **the oracle**. The GPU cut is held to agreeing with it exactly |
|
|
80
80
|
|
|
81
81
|
## 2. Phase 1 — the page decode has holes, and they are load-bearing
|
|
82
82
|
|
|
@@ -287,7 +287,7 @@ is resident but not selectable — its clusters' parents are split across pages
|
|
|
287
287
|
pages has not arrived. The clamp draws `C`'s parent `P`, correctly, standing in over that surface.
|
|
288
288
|
But `C` itself satisfies §4's form — `project(C.parent) > τ` and `project(C.self) ≤ τ` — so a
|
|
289
289
|
flat evaluation draws it as well, underneath `P`, and the depth buffer picks between two surfaces
|
|
290
|
-
a few microns apart. This is exactly the failure `
|
|
290
|
+
a few microns apart. This is exactly the failure `vgeo_select_cut.spec.js` was written to catch, and
|
|
291
291
|
the CPU traversal never meets it because *not entering a non-selectable group* is how it descends.
|
|
292
292
|
A predicate has to say so out loud:
|
|
293
293
|
|
|
@@ -535,7 +535,7 @@ Four tiers, in the order they catch things.
|
|
|
535
535
|
pages withheld. Multiset, not set: a duplicate is the failure mode that reads as corrupt
|
|
536
536
|
geometry rather than as a missing page, and a set comparison cannot see it.
|
|
537
537
|
|
|
538
|
-
**At 64 KB pages, not the 8 KB `
|
|
538
|
+
**At 64 KB pages, not the 8 KB `vgeo_select_cut.spec.js` uses** (REVIEW_LEDGER D2). The 8 KB fixture
|
|
539
539
|
is the one that puts a group's parents on either side of a page boundary thirteen times over,
|
|
540
540
|
which is what *that* spec is for — and it is the one fixture in which this spec's headline case
|
|
541
541
|
cannot occur: measured, 8 KB puts exactly one group in every page of this torus, so a blocked
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VGeoFeedbackLoop.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VGeoFeedbackLoop.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js"],"names":[],"mappings":"AAMA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH;IAqCI;;;;;;OAMG;IACH;QAL8C,OAAO,EAA1C,yBAAyB;QACF,SAAS,EAAhC,aAAa;QACI,aAAa,GAA9B,MAAM;OAUhB;IAED;;OAEG;IACH,4DAEC;IAED;;OAEG;IACH,yBAEC;IAED;;;;;;;OAOG;IACH,6BAEC;IAED;;OAEG;IACH,yBAEC;IAED;;OAEG;IACH,8BAEC;IAED;;OAEG;IACH,+BAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;;;;OAKG;IACH,YAHW,UAAU,GACR,OAAO,CAuDnB;IAwBD;;;;OAIG;IACH,SAFa,IAAI,CAIhB;IAED;;;;;;;OAOG;IACH,WAFa,IAAI,CAIhB;;CACJ;yBA1OY,OAAO,iEAAiE,EAAE,UAAU;wCACpF,OAAO,gCAAgC,EAAE,yBAAyB;4BAClE,OAAO,oBAAoB,EAAE,aAAa"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { assert } from "../../../../../core/assert.js";
|
|
2
2
|
import { graph_read_buffer } from "../../../buffer/graph_read_buffer.js";
|
|
3
|
+
import { VGEO_CUT_STAT } from "./layout/VGEO_CUT_STAT.js";
|
|
3
4
|
import { VGEO_CUT_STAT_COUNT } from "./layout/VGEO_CUT_STAT_COUNT.js";
|
|
4
5
|
import { VGEO_FEEDBACK_OFFSET } from "./layout/VGEO_FEEDBACK_OFFSET.js";
|
|
5
6
|
|
|
@@ -206,6 +207,15 @@ export class VGeoFeedbackLoop {
|
|
|
206
207
|
this.#stats[i] = words[VGEO_FEEDBACK_OFFSET.STATS + i];
|
|
207
208
|
}
|
|
208
209
|
|
|
210
|
+
/*
|
|
211
|
+
One counter is not a statistic, it is an instruction. `QUEUE_REMAINING` is non-zero exactly
|
|
212
|
+
when the descent ran out of wavefronts and abandoned subtrees it had not expanded — a hole
|
|
213
|
+
in the picture rather than a coarser surface — and this is the only moment anything on the
|
|
214
|
+
host learns it. The runtime owns what to do about it; the loop's job here is the same as
|
|
215
|
+
with a want, which is to carry the reading to whoever it is about.
|
|
216
|
+
*/
|
|
217
|
+
this.#runtime.note_incomplete_descent(this.#stats[VGEO_CUT_STAT.QUEUE_REMAINING]);
|
|
218
|
+
|
|
209
219
|
this.#residency.apply(words, layout, reading_frame);
|
|
210
220
|
}
|
|
211
221
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VGeoResidency.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VGeoResidency.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js"],"names":[],"mappings":"AA2GA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH;IAiKI;;;;;;;OAOG;IACH;QAN2C,IAAI,EAApC,sBAAsB;QACS,OAAO,GAAtC,oBAAoB;QACM,IAAI,GAA9B,eAAe;QACW,OAAO,GAAjC,eAAe;OA8BzB;IAID;;OAEG;IACH,oCAEC;IAED;;OAEG;IACH,4BAEC;IAED;;OAEG;IACH,+BAEC;IAED;;OAEG;IACH,yEAEC;IAED;;;;OAIG;IACH,oBAEC;IAED;;;;OAIG;IACH,gCAGC;IAED,+BAEC;IAED,iCAEC;IAED,6BAEC;IAED,2BAEC;IAED,iCAEC;IAED,gCAEC;IAED;;;;OAIG;IACH,oCAEC;IAED;;;OAGG;IACH,kCAEC;IAED;;;OAGG;IACH,kCAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;;OAGG;IACH,gCAEC;IAED;;;;;OAKG;IACH,gCAEC;IAED;;;OAGG;IACH,iCAEC;IAED,gCAEC;IAED,+BAEC;IAED,8BAEC;IAED;;OAEG;IACH,qCAQC;IAID;;;;;;;;;;OAUG;IACH,iBAHW,mBAAmB,GACjB,MAAM,CA8ClB;IAED;;;;;;OAMG;IACH,mBAHW,mBAAmB,GACjB,OAAO,CAgBnB;IAED;;;OAGG;IACH,sBAHW,mBAAmB,GACjB,OAAO,CAInB;IAED;;;;;;OAMG;IACH,cAJW,mBAAmB,cACnB,MAAM,GACJ,QAAQ,GAAC,UAAU,GAAC,aAAa,GAAC,KAAK,GAAC,MAAM,GAAC,cAAc,CAqBzE;IAgCD;;;;OAIG;IACH,SAFa,IAAI,CAOhB;IAED;;;;OAIG;IACH,WAFa,IAAI,CAUhB;IAED;;;;OAIG;IACH,qBAFa,MAAM,CAkBlB;IAID;;;;;;;;;OASG;IACH,aANW,WAAW,UACX;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAChF,UAAgB,EAAE,MAAM,CAAA;KAAC,iBACf,MAAM,GACJ,IAAI,CA6HhB;IA2FD;;;;;;OAMG;IACH,yBAHW,MAAM,GACJ,OAAO,CAgBnB;IAED;;;;;;OAMG;IACH,oBAHW,MAAM,GACJ,OAAO,CAoCnB;;CAqXJ;kCAr1CY,OAAO,uCAAuC,EAAE,mBAAmB;uBACnE,OAAO,4BAA4B,EAAE,QAAQ;qCAC7C,OAAO,6BAA6B,EAAE,sBAAsB;qCALpC,2BAA2B;gCALhC,gDAAgD;gCAIhD,sBAAsB"}
|
|
@@ -34,6 +34,18 @@ const NO_SLOT = 0xFFFFFFFF;
|
|
|
34
34
|
* @param {number} state
|
|
35
35
|
* @returns {number}
|
|
36
36
|
*/
|
|
37
|
+
/**
|
|
38
|
+
* Which of {@link VGeoResidency}'s two CLOCK hands is meant. They are an array rather than two
|
|
39
|
+
* fields so that one sweep can serve both tiers.
|
|
40
|
+
* @type {number}
|
|
41
|
+
*/
|
|
42
|
+
const HAND_VRAM = 0;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @type {number}
|
|
46
|
+
*/
|
|
47
|
+
const HAND_RAM = 1;
|
|
48
|
+
|
|
37
49
|
function tag_of(state) {
|
|
38
50
|
return state >>> TAG_SHIFT;
|
|
39
51
|
}
|
|
@@ -189,11 +201,6 @@ export class VGeoResidency {
|
|
|
189
201
|
*/
|
|
190
202
|
#vram_pinned;
|
|
191
203
|
|
|
192
|
-
/**
|
|
193
|
-
* @type {number}
|
|
194
|
-
*/
|
|
195
|
-
#vram_hand = 0;
|
|
196
|
-
|
|
197
204
|
// ------------------------------------------------------------------ the RAM tier
|
|
198
205
|
|
|
199
206
|
/**
|
|
@@ -229,11 +236,6 @@ export class VGeoResidency {
|
|
|
229
236
|
*/
|
|
230
237
|
#ram_free = [];
|
|
231
238
|
|
|
232
|
-
/**
|
|
233
|
-
* @type {number}
|
|
234
|
-
*/
|
|
235
|
-
#ram_hand = 0;
|
|
236
|
-
|
|
237
239
|
/**
|
|
238
240
|
* @type {number}
|
|
239
241
|
*/
|
|
@@ -253,6 +255,25 @@ export class VGeoResidency {
|
|
|
253
255
|
|
|
254
256
|
// ------------------------------------------------------------------ per reading
|
|
255
257
|
|
|
258
|
+
/**
|
|
259
|
+
* The CLOCK hands, {@link HAND_VRAM} and {@link HAND_RAM}. One array rather than two fields
|
|
260
|
+
* because {@link #next_victim} sweeps either tier and has to advance the one it was given.
|
|
261
|
+
* @type {Int32Array}
|
|
262
|
+
*/
|
|
263
|
+
#hands = new Int32Array(2);
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Bound once each, rather than per sweep: {@link #next_victim} takes the test as a function and
|
|
267
|
+
* is called per eviction, which is often enough that a closure a call would be a closure a call.
|
|
268
|
+
* @type {function(number): boolean}
|
|
269
|
+
*/
|
|
270
|
+
#is_evictable_vram = (page_row) => this.evictable_vram(page_row);
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @type {function(number): boolean}
|
|
274
|
+
*/
|
|
275
|
+
#is_evictable_ram = (slot) => this.evictable_ram(slot);
|
|
276
|
+
|
|
256
277
|
/**
|
|
257
278
|
* @type {number}
|
|
258
279
|
*/
|
|
@@ -1036,28 +1057,44 @@ export class VGeoResidency {
|
|
|
1036
1057
|
}
|
|
1037
1058
|
|
|
1038
1059
|
/**
|
|
1039
|
-
*
|
|
1060
|
+
* One tier's CLOCK hand, advanced under the reading's shared test budget.
|
|
1061
|
+
*
|
|
1062
|
+
* Both tiers sweep the same way — this is the "eviction is CLOCK under a test budget" bullet
|
|
1063
|
+
* above, and the only thing that differs between them is which array is being swept and what
|
|
1064
|
+
* makes an entry of it evictable. The budget is deliberately *not* per tier: a reading gets
|
|
1065
|
+
* `max_eviction_tests_per_reading` tests to spend across both, so a VRAM tier that is entirely
|
|
1066
|
+
* hot cannot also spend the RAM tier's allowance looking.
|
|
1040
1067
|
*
|
|
1041
|
-
* @
|
|
1068
|
+
* @param {number} hand {@link HAND_VRAM} or {@link HAND_RAM}
|
|
1069
|
+
* @param {number} capacity entries in that tier
|
|
1070
|
+
* @param {function(number): boolean} evictable
|
|
1071
|
+
* @returns {number} the index to evict, or -1 when the budget is spent without finding one
|
|
1042
1072
|
*/
|
|
1043
|
-
#
|
|
1044
|
-
const capacity = this.#vram_last_used.length;
|
|
1045
|
-
|
|
1073
|
+
#next_victim(hand, capacity, evictable) {
|
|
1046
1074
|
while (this.#tests_left > 0) {
|
|
1047
1075
|
this.#tests_left--;
|
|
1048
1076
|
|
|
1049
|
-
const
|
|
1077
|
+
const candidate = this.#hands[hand];
|
|
1050
1078
|
|
|
1051
|
-
this.#
|
|
1079
|
+
this.#hands[hand] = (candidate + 1) % capacity;
|
|
1052
1080
|
|
|
1053
|
-
if (
|
|
1054
|
-
return
|
|
1081
|
+
if (evictable(candidate)) {
|
|
1082
|
+
return candidate;
|
|
1055
1083
|
}
|
|
1056
1084
|
}
|
|
1057
1085
|
|
|
1058
1086
|
return -1;
|
|
1059
1087
|
}
|
|
1060
1088
|
|
|
1089
|
+
/**
|
|
1090
|
+
* @returns {number} page row, or -1
|
|
1091
|
+
*/
|
|
1092
|
+
#next_vram_victim() {
|
|
1093
|
+
return this.#next_victim(
|
|
1094
|
+
HAND_VRAM, this.#vram_last_used.length, this.#is_evictable_vram
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1061
1098
|
/**
|
|
1062
1099
|
* @param {number} page_row
|
|
1063
1100
|
*/
|
|
@@ -1113,21 +1150,9 @@ export class VGeoResidency {
|
|
|
1113
1150
|
* @returns {number} slot, or -1
|
|
1114
1151
|
*/
|
|
1115
1152
|
#next_ram_victim() {
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
this.#tests_left--;
|
|
1120
|
-
|
|
1121
|
-
const slot = this.#ram_hand;
|
|
1122
|
-
|
|
1123
|
-
this.#ram_hand = (slot + 1) % capacity;
|
|
1124
|
-
|
|
1125
|
-
if (this.evictable_ram(slot)) {
|
|
1126
|
-
return slot;
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
return -1;
|
|
1153
|
+
return this.#next_victim(
|
|
1154
|
+
HAND_RAM, this.#ram_geometry.length, this.#is_evictable_ram
|
|
1155
|
+
);
|
|
1131
1156
|
}
|
|
1132
1157
|
|
|
1133
1158
|
/**
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* an error.
|
|
2
|
+
* The arithmetic the cut rule is written in: where the camera is in an instance's own space, what
|
|
3
|
+
* an object-space error projects to in pixels, and whether a sphere is worth descending into at all.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* are reading the same numbers rather than two copies of them.
|
|
5
|
+
* Addressing moved to {@link chunk_vgeo_cut_arena}, which this pulls in — a pass that only wants to
|
|
6
|
+
* find a row should not have to take the frustum test with it, and the passes that did not want to
|
|
7
|
+
* wrote their own accessor instead.
|
|
9
8
|
*
|
|
10
|
-
* Every buffer named here has to be declared by the importing shader
|
|
11
|
-
* addressing across passes, and it is the same
|
|
9
|
+
* Every buffer named here has to be declared by the importing shader — `instances`, plus whatever
|
|
10
|
+
* the arena chunk needs. That is the price of sharing addressing across passes, and it is the same
|
|
11
|
+
* bargain `chunk_scene_database_access` makes.
|
|
12
12
|
*
|
|
13
13
|
* @author Alex Goldring
|
|
14
14
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk_vgeo_cut_access.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"chunk_vgeo_cut_access.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AACH,oCAFU,SAAS,CA+EQ;0BAjGD,0CAA0C"}
|
|
@@ -1,27 +1,18 @@
|
|
|
1
1
|
import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
|
|
2
|
-
import { VGEO_CLUSTER_ROW_WORDS } from "../layout/VGEO_CLUSTER_ROW_WORDS.js";
|
|
3
|
-
import { VGEO_GEOMETRY_ROW_WORDS } from "../layout/VGEO_GEOMETRY_ROW_WORDS.js";
|
|
4
|
-
import { VGEO_GROUP_ROW_WORDS } from "../layout/VGEO_GROUP_ROW_WORDS.js";
|
|
5
2
|
import { VGEO_INSTANCE_OFFSET } from "../layout/VGEO_INSTANCE_OFFSET.js";
|
|
6
|
-
import {
|
|
7
|
-
import { VGEO_NODE_ROW_LEAF_BIT } from "../layout/VGEO_NODE_ROW_LEAF_BIT.js";
|
|
8
|
-
import { VGEO_NODE_ROW_OFFSET } from "../layout/VGEO_NODE_ROW_OFFSET.js";
|
|
9
|
-
import { VGEO_NODE_ROW_WORDS } from "../layout/VGEO_NODE_ROW_WORDS.js";
|
|
10
|
-
import { VGEO_PAGE_ROW_OFFSET } from "../layout/VGEO_PAGE_ROW_OFFSET.js";
|
|
11
|
-
import { VGEO_PAGE_ROW_WORDS } from "../layout/VGEO_PAGE_ROW_WORDS.js";
|
|
12
|
-
import { VGEO_PARENT_ROW_WORDS } from "../layout/VGEO_PARENT_ROW_WORDS.js";
|
|
3
|
+
import { chunk_vgeo_cut_arena } from "./chunk_vgeo_cut_arena.js";
|
|
13
4
|
|
|
14
5
|
/**
|
|
15
|
-
*
|
|
16
|
-
* an error.
|
|
6
|
+
* The arithmetic the cut rule is written in: where the camera is in an instance's own space, what
|
|
7
|
+
* an object-space error projects to in pixels, and whether a sphere is worth descending into at all.
|
|
17
8
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* are reading the same numbers rather than two copies of them.
|
|
9
|
+
* Addressing moved to {@link chunk_vgeo_cut_arena}, which this pulls in — a pass that only wants to
|
|
10
|
+
* find a row should not have to take the frustum test with it, and the passes that did not want to
|
|
11
|
+
* wrote their own accessor instead.
|
|
22
12
|
*
|
|
23
|
-
* Every buffer named here has to be declared by the importing shader
|
|
24
|
-
* addressing across passes, and it is the same
|
|
13
|
+
* Every buffer named here has to be declared by the importing shader — `instances`, plus whatever
|
|
14
|
+
* the arena chunk needs. That is the price of sharing addressing across passes, and it is the same
|
|
15
|
+
* bargain `chunk_scene_database_access` makes.
|
|
25
16
|
*
|
|
26
17
|
* @author Alex Goldring
|
|
27
18
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -30,17 +21,6 @@ import { VGEO_PARENT_ROW_WORDS } from "../layout/VGEO_PARENT_ROW_WORDS.js";
|
|
|
30
21
|
export const chunk_vgeo_cut_access = CodeChunk.from(
|
|
31
22
|
//language=WGSL
|
|
32
23
|
`
|
|
33
|
-
const VG_PAGE_ROW_WORDS = ${VGEO_PAGE_ROW_WORDS}u;
|
|
34
|
-
const VG_NODE_ROW_WORDS = ${VGEO_NODE_ROW_WORDS}u;
|
|
35
|
-
const VG_GROUP_ROW_WORDS = ${VGEO_GROUP_ROW_WORDS}u;
|
|
36
|
-
const VG_CLUSTER_ROW_WORDS = ${VGEO_CLUSTER_ROW_WORDS}u;
|
|
37
|
-
const VG_PARENT_ROW_WORDS = ${VGEO_PARENT_ROW_WORDS}u;
|
|
38
|
-
const VG_INSTANCE_WORDS = ${VGEO_INSTANCE_WORDS}u;
|
|
39
|
-
const VG_GEOMETRY_ROW_WORDS = ${VGEO_GEOMETRY_ROW_WORDS}u;
|
|
40
|
-
|
|
41
|
-
const VG_NODE_LEAF_BIT = ${VGEO_NODE_ROW_LEAF_BIT}u;
|
|
42
|
-
const VG_NODE_CHILD_COUNT_MASK = 0xffu;
|
|
43
|
-
|
|
44
24
|
/**
|
|
45
25
|
* Any error at or above this is the root's +infinity, however the file spelled it.
|
|
46
26
|
*
|
|
@@ -51,63 +31,6 @@ const VG_NODE_CHILD_COUNT_MASK = 0xffu;
|
|
|
51
31
|
const VG_ERROR_INFINITE = 3.0e38;
|
|
52
32
|
const VG_PROJECTION_MAX = 3.4e38;
|
|
53
33
|
|
|
54
|
-
/**
|
|
55
|
-
* A page's slot: its header, then its node, group and cluster rows.
|
|
56
|
-
*
|
|
57
|
-
* The stride is a uniform rather than a constant because the tier derives it from the page size its
|
|
58
|
-
* containers are bounded at, and it is a **multiply** rather than a table read because format
|
|
59
|
-
* §11.14 made that legal — design §6 asked for fixed-size page slots from the start and the bound
|
|
60
|
-
* is what it was waiting for. There is no page table, no allocator, and no second storage binding
|
|
61
|
-
* to keep coherent with this one.
|
|
62
|
-
*/
|
|
63
|
-
fn vg_slot_base(page_row: u32) -> u32 {
|
|
64
|
-
return page_row * params.page_slot_words;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
fn vg_page_field(page_row: u32, field: u32) -> u32 {
|
|
68
|
-
return vg_arena[vg_slot_base(page_row) + field];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
fn vg_node_base(page_row: u32) -> u32 {
|
|
72
|
-
return vg_slot_base(page_row) + VG_PAGE_ROW_WORDS;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
fn vg_group_base(page_row: u32) -> u32 {
|
|
76
|
-
return vg_node_base(page_row)
|
|
77
|
-
+ vg_page_field(page_row, ${VGEO_PAGE_ROW_OFFSET.NODE_COUNT}u) * VG_NODE_ROW_WORDS;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
fn vg_cluster_base(page_row: u32) -> u32 {
|
|
81
|
-
return vg_group_base(page_row)
|
|
82
|
-
+ vg_page_field(page_row, ${VGEO_PAGE_ROW_OFFSET.GROUP_COUNT}u) * VG_GROUP_ROW_WORDS;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* The fourth section: this page's parent rows, which is where a walk *up* reads.
|
|
87
|
-
*
|
|
88
|
-
* It may be empty, and a reader has to check rather than assume: the page row's parent
|
|
89
|
-
* entry count is zero for
|
|
90
|
-
* every page of a container written before format 4, which has no upward edge at all. Zero is not a
|
|
91
|
-
* malformed page; it is an asset that can only be re-descended.
|
|
92
|
-
*/
|
|
93
|
-
fn vg_parent_base(page_row: u32) -> u32 {
|
|
94
|
-
return vg_cluster_base(page_row)
|
|
95
|
-
+ vg_page_field(page_row, ${VGEO_PAGE_ROW_OFFSET.CLUSTER_COUNT}u) * VG_CLUSTER_ROW_WORDS;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
fn vg_arena_f32(word: u32) -> f32 {
|
|
99
|
-
return bitcast<f32>(vg_arena[word]);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
fn vg_sphere_at(word: u32) -> vec4<f32> {
|
|
103
|
-
return vec4<f32>(
|
|
104
|
-
bitcast<f32>(vg_arena[word]),
|
|
105
|
-
bitcast<f32>(vg_arena[word + 1u]),
|
|
106
|
-
bitcast<f32>(vg_arena[word + 2u]),
|
|
107
|
-
bitcast<f32>(vg_arena[word + 3u])
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
34
|
fn vg_instance_f32(instance_base: u32, field: u32) -> f32 {
|
|
112
35
|
return bitcast<f32>(instances[instance_base + field]);
|
|
113
36
|
}
|
|
@@ -123,7 +46,7 @@ fn vg_instance_eye(instance_base: u32) -> vec3<f32> {
|
|
|
123
46
|
/**
|
|
124
47
|
* \`err_px = r_e * screen_height / (2 * tan(fov_y / 2) * d)\`, with \`d\` the distance to the
|
|
125
48
|
* **closest point** of the sphere — design §4, and written in that order so that it agrees with
|
|
126
|
-
* \`
|
|
49
|
+
* \`vgeo_select_cut\` term for term rather than merely in the limit.
|
|
127
50
|
*
|
|
128
51
|
* Two conventions carry real weight. A zero error projects to zero **unconditionally**, so a leaf
|
|
129
52
|
* — whose error is exactly zero — does not become undrawable the moment the camera enters its
|
|
@@ -172,4 +95,4 @@ fn vg_sphere_outside_frustum(instance_base: u32, sphere: vec4<f32>) -> bool {
|
|
|
172
95
|
|
|
173
96
|
return false;
|
|
174
97
|
}
|
|
175
|
-
`, []);
|
|
98
|
+
`, [chunk_vgeo_cut_arena]);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a row is, in the arena — and nothing else.
|
|
3
|
+
*
|
|
4
|
+
* Split out of {@link chunk_vgeo_cut_access} because three passes want an address and only one of
|
|
5
|
+
* them wants a projection. Before the split, a pass that needed one field of a page header wrote
|
|
6
|
+
* its own accessor rather than take a chunk that also declares the frustum test, the instance eye
|
|
7
|
+
* and the error projection; `shader_vgeo_cut_reseed` said so where its copy was
|
|
8
|
+
* (`vg_reseed_page_field`). The answer to "the chunk declares more than this pass binds" is a
|
|
9
|
+
* smaller chunk, not a second accessor.
|
|
10
|
+
*
|
|
11
|
+
* Requires the importing shader to declare `params` and `vg_arena`.
|
|
12
|
+
*
|
|
13
|
+
* @author Alex Goldring
|
|
14
|
+
* @copyright Company Named Limited (c) 2026
|
|
15
|
+
* @type {CodeChunk}
|
|
16
|
+
*/
|
|
17
|
+
export const chunk_vgeo_cut_arena: CodeChunk;
|
|
18
|
+
import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
|
|
19
|
+
//# sourceMappingURL=chunk_vgeo_cut_arena.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk_vgeo_cut_arena.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;GAeG;AACH,mCAFU,SAAS,CAwEZ;0BAjGmB,0CAA0C"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
|
|
2
|
+
import { VGEO_CLUSTER_ROW_WORDS } from "../layout/VGEO_CLUSTER_ROW_WORDS.js";
|
|
3
|
+
import { VGEO_GEOMETRY_ROW_WORDS } from "../layout/VGEO_GEOMETRY_ROW_WORDS.js";
|
|
4
|
+
import { VGEO_GROUP_ROW_WORDS } from "../layout/VGEO_GROUP_ROW_WORDS.js";
|
|
5
|
+
import { VGEO_INSTANCE_WORDS } from "../layout/VGEO_INSTANCE_WORDS.js";
|
|
6
|
+
import { VGEO_NODE_ROW_LEAF_BIT } from "../layout/VGEO_NODE_ROW_LEAF_BIT.js";
|
|
7
|
+
import { VGEO_NODE_ROW_WORDS } from "../layout/VGEO_NODE_ROW_WORDS.js";
|
|
8
|
+
import { VGEO_PAGE_ROW_OFFSET } from "../layout/VGEO_PAGE_ROW_OFFSET.js";
|
|
9
|
+
import { VGEO_PAGE_ROW_WORDS } from "../layout/VGEO_PAGE_ROW_WORDS.js";
|
|
10
|
+
import { VGEO_PARENT_ROW_WORDS } from "../layout/VGEO_PARENT_ROW_WORDS.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Where a row is, in the arena — and nothing else.
|
|
14
|
+
*
|
|
15
|
+
* Split out of {@link chunk_vgeo_cut_access} because three passes want an address and only one of
|
|
16
|
+
* them wants a projection. Before the split, a pass that needed one field of a page header wrote
|
|
17
|
+
* its own accessor rather than take a chunk that also declares the frustum test, the instance eye
|
|
18
|
+
* and the error projection; `shader_vgeo_cut_reseed` said so where its copy was
|
|
19
|
+
* (`vg_reseed_page_field`). The answer to "the chunk declares more than this pass binds" is a
|
|
20
|
+
* smaller chunk, not a second accessor.
|
|
21
|
+
*
|
|
22
|
+
* Requires the importing shader to declare `params` and `vg_arena`.
|
|
23
|
+
*
|
|
24
|
+
* @author Alex Goldring
|
|
25
|
+
* @copyright Company Named Limited (c) 2026
|
|
26
|
+
* @type {CodeChunk}
|
|
27
|
+
*/
|
|
28
|
+
export const chunk_vgeo_cut_arena = CodeChunk.from(
|
|
29
|
+
//language=WGSL
|
|
30
|
+
`
|
|
31
|
+
const VG_PAGE_ROW_WORDS = ${VGEO_PAGE_ROW_WORDS}u;
|
|
32
|
+
const VG_NODE_ROW_WORDS = ${VGEO_NODE_ROW_WORDS}u;
|
|
33
|
+
const VG_GROUP_ROW_WORDS = ${VGEO_GROUP_ROW_WORDS}u;
|
|
34
|
+
const VG_CLUSTER_ROW_WORDS = ${VGEO_CLUSTER_ROW_WORDS}u;
|
|
35
|
+
const VG_PARENT_ROW_WORDS = ${VGEO_PARENT_ROW_WORDS}u;
|
|
36
|
+
const VG_INSTANCE_WORDS = ${VGEO_INSTANCE_WORDS}u;
|
|
37
|
+
const VG_GEOMETRY_ROW_WORDS = ${VGEO_GEOMETRY_ROW_WORDS}u;
|
|
38
|
+
|
|
39
|
+
const VG_NODE_LEAF_BIT = ${VGEO_NODE_ROW_LEAF_BIT}u;
|
|
40
|
+
const VG_NODE_CHILD_COUNT_MASK = 0xffu;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A page's slot: its header, then its node, group and cluster rows.
|
|
44
|
+
*
|
|
45
|
+
* The stride is a uniform rather than a constant because the tier derives it from the page size its
|
|
46
|
+
* containers are bounded at, and it is a **multiply** rather than a table read because format
|
|
47
|
+
* §11.14 made that legal — design §6 asked for fixed-size page slots from the start and the bound
|
|
48
|
+
* is what it was waiting for. There is no page table, no allocator, and no second storage binding
|
|
49
|
+
* to keep coherent with this one.
|
|
50
|
+
*/
|
|
51
|
+
fn vg_slot_base(page_row: u32) -> u32 {
|
|
52
|
+
return page_row * params.page_slot_words;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fn vg_page_field(page_row: u32, field: u32) -> u32 {
|
|
56
|
+
return vg_arena[vg_slot_base(page_row) + field];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn vg_node_base(page_row: u32) -> u32 {
|
|
60
|
+
return vg_slot_base(page_row) + VG_PAGE_ROW_WORDS;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fn vg_group_base(page_row: u32) -> u32 {
|
|
64
|
+
return vg_node_base(page_row)
|
|
65
|
+
+ vg_page_field(page_row, ${VGEO_PAGE_ROW_OFFSET.NODE_COUNT}u) * VG_NODE_ROW_WORDS;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fn vg_cluster_base(page_row: u32) -> u32 {
|
|
69
|
+
return vg_group_base(page_row)
|
|
70
|
+
+ vg_page_field(page_row, ${VGEO_PAGE_ROW_OFFSET.GROUP_COUNT}u) * VG_GROUP_ROW_WORDS;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The fourth section: this page's parent rows, which is where a walk *up* reads.
|
|
75
|
+
*
|
|
76
|
+
* It may be empty, and a reader has to check rather than assume: the page row's parent
|
|
77
|
+
* entry count is zero for
|
|
78
|
+
* every page of a container written before format 4, which has no upward edge at all. Zero is not a
|
|
79
|
+
* malformed page; it is an asset that can only be re-descended.
|
|
80
|
+
*/
|
|
81
|
+
fn vg_parent_base(page_row: u32) -> u32 {
|
|
82
|
+
return vg_cluster_base(page_row)
|
|
83
|
+
+ vg_page_field(page_row, ${VGEO_PAGE_ROW_OFFSET.CLUSTER_COUNT}u) * VG_CLUSTER_ROW_WORDS;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fn vg_arena_f32(word: u32) -> f32 {
|
|
87
|
+
return bitcast<f32>(vg_arena[word]);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
fn vg_sphere_at(word: u32) -> vec4<f32> {
|
|
91
|
+
return vec4<f32>(
|
|
92
|
+
bitcast<f32>(vg_arena[word]),
|
|
93
|
+
bitcast<f32>(vg_arena[word + 1u]),
|
|
94
|
+
bitcast<f32>(vg_arena[word + 2u]),
|
|
95
|
+
bitcast<f32>(vg_arena[word + 3u])
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
`, []);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One page, claimed once per instance, and touched when the claim is won.
|
|
3
|
+
*
|
|
4
|
+
* This is the invariant the whole cut rests on — "at most one draw record per (instance, cluster)" —
|
|
5
|
+
* and it was written out three times: here's-the-original in `shader_vgeo_cut_traverse`, a
|
|
6
|
+
* line-for-line copy in `shader_vgeo_cut_reseed`, and inline in `shader_vgeo_cut_seed`. The
|
|
7
|
+
* copies had already begun to differ: the seed pass omitted the `claim_word_count` bound the other
|
|
8
|
+
* two take. It was correct — the seed pass establishes that bound a few lines earlier — but a
|
|
9
|
+
* correctness invariant whose three spellings disagree about which checks it needs is one nobody
|
|
10
|
+
* can read off the source any more.
|
|
11
|
+
*
|
|
12
|
+
* The touch is the other half and travels with it, because a claim that does not stamp the page is
|
|
13
|
+
* a page that ages out of the LRU while it is on screen. LRU on last-**touched**, never on
|
|
14
|
+
* last-wanted: stamping at fetch time freezes the stamp of exactly the pages that are being drawn
|
|
15
|
+
* and evicts them, which is the fallback-chain bug the virtual texture cache already keys on touch
|
|
16
|
+
* to avoid.
|
|
17
|
+
*
|
|
18
|
+
* One bit per page row, because the feedback buffer is per frame rather than per invocation: the
|
|
19
|
+
* bit dedups across every view and bucket of the frame and is the record the host reads, so there
|
|
20
|
+
* is no list to fill and no touch a full list could lose.
|
|
21
|
+
*
|
|
22
|
+
* Requires the importing shader to declare `params`, `vg_arena`, `instances`, `claim` and
|
|
23
|
+
* `feedback`.
|
|
24
|
+
*
|
|
25
|
+
* @author Alex Goldring
|
|
26
|
+
* @copyright Company Named Limited (c) 2026
|
|
27
|
+
* @type {CodeChunk}
|
|
28
|
+
*/
|
|
29
|
+
export const chunk_vgeo_cut_claim: CodeChunk;
|
|
30
|
+
import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
|
|
31
|
+
//# sourceMappingURL=chunk_vgeo_cut_claim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk_vgeo_cut_claim.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,mCAFU,SAAS,CAiEQ;0BAlGD,0CAA0C"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
|
|
2
|
+
import { VGEO_CUT_STAT } from "../layout/VGEO_CUT_STAT.js";
|
|
3
|
+
import { VGEO_FEEDBACK_OFFSET } from "../layout/VGEO_FEEDBACK_OFFSET.js";
|
|
4
|
+
import { VGEO_INSTANCE_OFFSET } from "../layout/VGEO_INSTANCE_OFFSET.js";
|
|
5
|
+
import { VGEO_PAGE_ROW_OFFSET } from "../layout/VGEO_PAGE_ROW_OFFSET.js";
|
|
6
|
+
import { chunk_vgeo_cut_arena } from "./chunk_vgeo_cut_arena.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* One page, claimed once per instance, and touched when the claim is won.
|
|
10
|
+
*
|
|
11
|
+
* This is the invariant the whole cut rests on — "at most one draw record per (instance, cluster)" —
|
|
12
|
+
* and it was written out three times: here's-the-original in `shader_vgeo_cut_traverse`, a
|
|
13
|
+
* line-for-line copy in `shader_vgeo_cut_reseed`, and inline in `shader_vgeo_cut_seed`. The
|
|
14
|
+
* copies had already begun to differ: the seed pass omitted the `claim_word_count` bound the other
|
|
15
|
+
* two take. It was correct — the seed pass establishes that bound a few lines earlier — but a
|
|
16
|
+
* correctness invariant whose three spellings disagree about which checks it needs is one nobody
|
|
17
|
+
* can read off the source any more.
|
|
18
|
+
*
|
|
19
|
+
* The touch is the other half and travels with it, because a claim that does not stamp the page is
|
|
20
|
+
* a page that ages out of the LRU while it is on screen. LRU on last-**touched**, never on
|
|
21
|
+
* last-wanted: stamping at fetch time freezes the stamp of exactly the pages that are being drawn
|
|
22
|
+
* and evicts them, which is the fallback-chain bug the virtual texture cache already keys on touch
|
|
23
|
+
* to avoid.
|
|
24
|
+
*
|
|
25
|
+
* One bit per page row, because the feedback buffer is per frame rather than per invocation: the
|
|
26
|
+
* bit dedups across every view and bucket of the frame and is the record the host reads, so there
|
|
27
|
+
* is no list to fill and no touch a full list could lose.
|
|
28
|
+
*
|
|
29
|
+
* Requires the importing shader to declare `params`, `vg_arena`, `instances`, `claim` and
|
|
30
|
+
* `feedback`.
|
|
31
|
+
*
|
|
32
|
+
* @author Alex Goldring
|
|
33
|
+
* @copyright Company Named Limited (c) 2026
|
|
34
|
+
* @type {CodeChunk}
|
|
35
|
+
*/
|
|
36
|
+
export const chunk_vgeo_cut_claim = CodeChunk.from(
|
|
37
|
+
//language=WGSL
|
|
38
|
+
`
|
|
39
|
+
fn vg_stat(slot: u32, amount: u32) {
|
|
40
|
+
atomicAdd(&feedback[${VGEO_FEEDBACK_OFFSET.STATS}u + slot], amount);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Record that this page was selected from this frame — design §6's eviction key.
|
|
45
|
+
*/
|
|
46
|
+
fn vg_touch_page(page_row: u32) {
|
|
47
|
+
atomicOr(&feedback[params.touch_bits_base + (page_row >> 5u)], 1u << (page_row & 31u));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The claim itself, against a slice of the bitmask the caller already has in hand.
|
|
52
|
+
*
|
|
53
|
+
* Taken this way rather than always through the instance record because the seed pass computes the
|
|
54
|
+
* slice base in the same invocation that claims with it — it has just written it to the instance
|
|
55
|
+
* record, and reading it straight back would be a storage round trip for a value already in a
|
|
56
|
+
* register.
|
|
57
|
+
*
|
|
58
|
+
* @returns whether this invocation is the one that claimed the page
|
|
59
|
+
*/
|
|
60
|
+
fn vg_claim_page_at(claim_base: u32, ordinal_capacity: u32, page_row: u32) -> bool {
|
|
61
|
+
let ordinal = vg_page_field(page_row, ${VGEO_PAGE_ROW_OFFSET.ORDINAL}u);
|
|
62
|
+
|
|
63
|
+
if (ordinal >= ordinal_capacity) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let bit = claim_base + ordinal;
|
|
68
|
+
|
|
69
|
+
let word = bit >> 5u;
|
|
70
|
+
|
|
71
|
+
if (word >= params.claim_word_count) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let mask = 1u << (bit & 31u);
|
|
76
|
+
|
|
77
|
+
if ((atomicOr(&claim[word], mask) & mask) != 0u) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
vg_stat(${VGEO_CUT_STAT.PAGES}u, 1u);
|
|
82
|
+
|
|
83
|
+
vg_touch_page(page_row);
|
|
84
|
+
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The same claim, for a caller holding an instance rather than its slice. An instance whose slice
|
|
90
|
+
* of the bitmask does not fit is refused upstream, in the seed pass, rather than run unclaimed.
|
|
91
|
+
*/
|
|
92
|
+
fn vg_claim_page(instance_base: u32, page_row: u32) -> bool {
|
|
93
|
+
return vg_claim_page_at(
|
|
94
|
+
instances[instance_base + ${VGEO_INSTANCE_OFFSET.CLAIM_BASE}u],
|
|
95
|
+
instances[instance_base + ${VGEO_INSTANCE_OFFSET.ORDINAL_CAPACITY}u],
|
|
96
|
+
page_row
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
`, [chunk_vgeo_cut_arena]);
|