@woosh/meep-engine 3.26.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.
Files changed (449) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +542 -0
  4. package/src/core/binary/lz4/LZ4_LEVEL.d.ts +33 -0
  5. package/src/core/binary/lz4/LZ4_LEVEL.d.ts.map +1 -0
  6. package/src/core/binary/lz4/LZ4_LEVEL.js +32 -0
  7. package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts +33 -0
  8. package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts.map +1 -0
  9. package/src/core/binary/lz4/lz4_compress_block_at_level.js +47 -0
  10. package/src/core/binary/lz4/lz4_compress_block_hc.d.ts +40 -0
  11. package/src/core/binary/lz4/lz4_compress_block_hc.d.ts.map +1 -0
  12. package/src/core/binary/lz4/lz4_compress_block_hc.js +1382 -0
  13. package/src/core/binary/lz4/lz4_decompress_block.d.ts +2 -1
  14. package/src/core/binary/lz4/lz4_decompress_block.d.ts.map +1 -1
  15. package/src/core/binary/lz4/lz4_decompress_block.js +31 -6
  16. package/src/core/geom/3d/mat4/m4_linear_determinant.d.ts +15 -0
  17. package/src/core/geom/3d/mat4/m4_linear_determinant.d.ts.map +1 -0
  18. package/src/core/geom/3d/mat4/m4_linear_determinant.js +24 -0
  19. package/src/core/geom/3d/mat4/m4_normal_matrix3.d.ts +4 -2
  20. package/src/core/geom/3d/mat4/m4_normal_matrix3.d.ts.map +1 -1
  21. package/src/core/geom/3d/mat4/m4_normal_matrix3.js +21 -11
  22. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +14 -7
  23. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
  24. package/src/core/geom/3d/shape/HeightMapShape3D.js +87 -78
  25. package/src/engine/Engine.d.ts.map +1 -1
  26. package/src/engine/Engine.js +38 -1
  27. package/src/engine/graphics3/GraphicsEngine.d.ts +5 -1
  28. package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -1
  29. package/src/engine/graphics3/GraphicsEngine.js +834 -830
  30. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  31. package/src/shade/RENDERER_CONTRACT.md +19 -10
  32. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +1 -1
  33. package/src/shade/playground/vgeo_runtime/README.md +186 -27
  34. package/src/shade/playground/vgeo_runtime/index.html +112 -62
  35. package/src/shade/playground/vgeo_runtime/main.js +678 -88
  36. package/src/shade/playground/vgeo_runtime/sample_asset.d.ts +18 -0
  37. package/src/shade/playground/vgeo_runtime/sample_asset.d.ts.map +1 -0
  38. package/src/shade/playground/{vgeo_viewer → vgeo_runtime}/sample_asset.js +23 -5
  39. package/src/shade/playground/vgeo_scene/README.md +408 -0
  40. package/src/shade/playground/vgeo_scene/index.html +144 -0
  41. package/src/shade/playground/vgeo_scene/main.d.ts +2 -0
  42. package/src/shade/playground/vgeo_scene/main.d.ts.map +1 -0
  43. package/src/shade/playground/vgeo_scene/main.js +1716 -0
  44. package/src/shade/playground/vgeo_viewer/sample_asset.d.ts.map +1 -1
  45. package/src/shade/renderer/Renderer.d.ts +4 -1
  46. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  47. package/src/shade/renderer/Renderer.js +5 -2
  48. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +1 -2
  49. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +11 -0
  50. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  51. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +16 -8
  52. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  53. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +16 -11
  54. package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts.map +1 -1
  55. package/src/shade/renderer/geometry/meshlet/MeshletBatch.js +3 -29
  56. package/src/shade/renderer/geometry/meshlet/encoding/ENCODED_ATTRIBUTE_DEFAULT_VALUES.d.ts +22 -0
  57. package/src/shade/renderer/geometry/meshlet/encoding/ENCODED_ATTRIBUTE_DEFAULT_VALUES.d.ts.map +1 -0
  58. package/src/shade/renderer/geometry/meshlet/encoding/ENCODED_ATTRIBUTE_DEFAULT_VALUES.js +49 -0
  59. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +77 -7
  60. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +36 -23
  61. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +17 -14
  62. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +19 -1
  63. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  64. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +21 -1
  65. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.d.ts.map +1 -1
  66. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +5 -9
  67. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevel.d.ts +32 -0
  68. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevel.d.ts.map +1 -0
  69. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts +59 -0
  70. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts.map +1 -0
  71. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelSummary.d.ts +44 -0
  72. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelSummary.d.ts.map +1 -0
  73. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts +36 -0
  74. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts.map +1 -0
  75. package/src/shade/renderer/geometry/virtual/build/{vgeo_build_levels.js → level/vgeo_build_levels.js} +61 -95
  76. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_root_group.d.ts +19 -0
  77. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_root_group.d.ts.map +1 -0
  78. package/src/shade/renderer/geometry/virtual/build/{vgeo_build_root_group.js → level/vgeo_build_root_group.js} +1 -1
  79. package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts +73 -0
  80. package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts.map +1 -0
  81. package/src/shade/renderer/geometry/virtual/build/{VirtualGeometryMesh.js → mesh/VirtualGeometryMesh.js} +7 -7
  82. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts +29 -0
  83. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts.map +1 -0
  84. package/src/shade/renderer/geometry/virtual/build/{vgeo_compute_vertex_normals.js → mesh/vgeo_compute_vertex_normals.js} +3 -3
  85. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts +31 -0
  86. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts.map +1 -0
  87. package/src/shade/renderer/geometry/virtual/build/{vgeo_compute_vertex_tangents.js → mesh/vgeo_compute_vertex_tangents.js} +5 -5
  88. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts +46 -0
  89. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts.map +1 -0
  90. package/src/shade/renderer/geometry/virtual/build/{vgeo_normalize_source.js → mesh/vgeo_normalize_source.js} +9 -9
  91. package/src/shade/renderer/geometry/virtual/build/page/vgeo_assemble_pages.d.ts +13 -0
  92. package/src/shade/renderer/geometry/virtual/build/page/vgeo_assemble_pages.d.ts.map +1 -0
  93. package/src/shade/renderer/geometry/virtual/build/{vgeo_assemble_pages.js → page/vgeo_assemble_pages.js} +63 -16
  94. package/src/shade/renderer/geometry/virtual/build/page/vgeo_build_page_nodes.d.ts +13 -0
  95. package/src/shade/renderer/geometry/virtual/build/page/vgeo_build_page_nodes.d.ts.map +1 -0
  96. package/src/shade/renderer/geometry/virtual/build/{vgeo_build_page_nodes.js → page/vgeo_build_page_nodes.js} +4 -4
  97. package/src/shade/renderer/geometry/virtual/build/page/vgeo_page_node_count.d.ts +22 -0
  98. package/src/shade/renderer/geometry/virtual/build/page/vgeo_page_node_count.d.ts.map +1 -0
  99. package/src/shade/renderer/geometry/virtual/build/{vgeo_page_node_count.js → page/vgeo_page_node_count.js} +2 -2
  100. package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts +52 -0
  101. package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts.map +1 -0
  102. package/src/shade/renderer/geometry/virtual/build/{VGeoFaceGraph.js → partition/VGeoFaceGraph.js} +1 -1
  103. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts +14 -0
  104. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts.map +1 -0
  105. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_graph.d.ts +29 -0
  106. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_graph.d.ts.map +1 -0
  107. package/src/shade/renderer/geometry/virtual/build/{vgeo_partition_graph.js → partition/vgeo_partition_graph.js} +2 -2
  108. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_subgraph.d.ts +41 -0
  109. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_subgraph.d.ts.map +1 -0
  110. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_subgraph.js +92 -0
  111. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set.d.ts +10 -0
  112. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set.d.ts.map +1 -0
  113. package/src/shade/renderer/geometry/virtual/build/{vgeo_split_face_set.js → partition/vgeo_split_face_set.js} +12 -55
  114. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts +15 -0
  115. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts.map +1 -0
  116. package/src/shade/renderer/geometry/virtual/build/{vgeo_split_face_set_packed.js → partition/vgeo_split_face_set_packed.js} +3 -3
  117. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_bounding_sphere.d.ts +12 -0
  118. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_bounding_sphere.d.ts.map +1 -0
  119. package/src/shade/renderer/geometry/virtual/build/{vgeo_bounding_sphere.js → sphere/vgeo_bounding_sphere.js} +3 -3
  120. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_containing_sphere.d.ts +18 -0
  121. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_containing_sphere.d.ts.map +1 -0
  122. package/src/shade/renderer/geometry/virtual/build/{vgeo_containing_sphere.js → sphere/vgeo_containing_sphere.js} +3 -3
  123. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_sphere_inflate_to_contain.d.ts +9 -0
  124. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_sphere_inflate_to_contain.d.ts.map +1 -0
  125. package/src/shade/renderer/geometry/virtual/build/{vgeo_sphere_inflate_to_contain.js → sphere/vgeo_sphere_inflate_to_contain.js} +1 -1
  126. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts +24 -0
  127. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts.map +1 -0
  128. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts +20 -0
  129. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts.map +1 -0
  130. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts +14 -0
  131. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts.map +1 -0
  132. package/src/shade/renderer/geometry/virtual/build/{vgeo_extract_submesh.js → submesh/vgeo_extract_submesh.js} +5 -5
  133. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts +12 -0
  134. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts.map +1 -0
  135. package/src/shade/renderer/geometry/virtual/build/{vgeo_gather_faces.js → submesh/vgeo_gather_faces.js} +2 -2
  136. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_narrow_indices.d.ts +11 -0
  137. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_narrow_indices.d.ts.map +1 -0
  138. package/src/shade/renderer/geometry/virtual/build/{vgeo_narrow_indices.js → submesh/vgeo_narrow_indices.js} +3 -3
  139. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
  140. package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts.map +1 -1
  141. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +10 -11
  142. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +22 -0
  143. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
  144. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +24 -0
  145. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.d.ts +8 -2
  146. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.d.ts.map +1 -1
  147. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +8 -2
  148. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts +12 -0
  149. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts.map +1 -1
  150. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +13 -0
  151. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts +8 -1
  152. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts.map +1 -1
  153. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +11 -3
  154. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts +9 -0
  155. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts.map +1 -1
  156. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +10 -1
  157. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_OFFSET.d.ts +15 -0
  158. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_OFFSET.d.ts.map +1 -0
  159. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_OFFSET.js +15 -0
  160. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts +18 -0
  161. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts.map +1 -0
  162. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.js +17 -0
  163. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts +8 -0
  164. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts.map +1 -0
  165. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.js +7 -0
  166. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.d.ts +3 -0
  167. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -0
  168. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts +14 -0
  169. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts.map +1 -0
  170. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.js +13 -0
  171. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts +11 -0
  172. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts.map +1 -0
  173. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.js +10 -0
  174. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts +28 -0
  175. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts.map +1 -1
  176. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +7 -3
  177. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +20 -0
  178. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
  179. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +20 -2
  180. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +4 -0
  181. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
  182. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +4 -0
  183. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +29 -3
  184. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
  185. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +81 -122
  186. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +40 -0
  187. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
  188. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +44 -0
  189. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts +69 -0
  190. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts.map +1 -0
  191. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.js +236 -0
  192. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +14 -0
  193. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
  194. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +15 -0
  195. package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts +31 -0
  196. package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts.map +1 -0
  197. package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.js +32 -0
  198. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +10 -0
  199. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
  200. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +21 -1
  201. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts +15 -0
  202. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts.map +1 -0
  203. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.js +84 -0
  204. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts +22 -0
  205. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts.map +1 -0
  206. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.js +96 -0
  207. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  208. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +63 -3
  209. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  210. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +219 -17
  211. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  212. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +156 -11
  213. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +656 -0
  214. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +33 -36
  215. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -1
  216. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +109 -193
  217. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +109 -29
  218. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
  219. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +173 -105
  220. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +37 -0
  221. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +109 -26
  222. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +548 -0
  223. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +29 -50
  224. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -1
  225. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +55 -487
  226. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts +84 -0
  227. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts.map +1 -0
  228. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js +393 -0
  229. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts +234 -0
  230. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts.map +1 -0
  231. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js +1388 -0
  232. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts +81 -0
  233. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts.map +1 -0
  234. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.js +89 -0
  235. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +53 -34
  236. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -1
  237. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +407 -124
  238. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts +100 -0
  239. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts.map +1 -0
  240. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.js +219 -0
  241. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts +17 -0
  242. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts.map +1 -0
  243. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.js +47 -0
  244. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts +20 -0
  245. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts.map +1 -0
  246. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.js +19 -0
  247. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -1
  248. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +30 -12
  249. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +8 -8
  250. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -1
  251. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +11 -73
  252. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.d.ts +19 -0
  253. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.d.ts.map +1 -0
  254. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.js +98 -0
  255. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.d.ts +31 -0
  256. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.d.ts.map +1 -0
  257. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.js +99 -0
  258. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_queue.d.ts +17 -0
  259. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_queue.d.ts.map +1 -0
  260. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_queue.js +39 -0
  261. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -1
  262. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +18 -1
  263. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -1
  264. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +5 -15
  265. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts +3 -0
  266. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts.map +1 -0
  267. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.js +77 -0
  268. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts +3 -0
  269. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts.map +1 -0
  270. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.js +130 -0
  271. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -1
  272. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +32 -37
  273. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -1
  274. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +576 -230
  275. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +15 -18
  276. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -1
  277. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +19 -28
  278. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
  279. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +45 -25
  280. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +1 -0
  281. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +11 -0
  282. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +1 -1
  283. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +0 -1
  284. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +12 -10
  285. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +1 -0
  286. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +8 -0
  287. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +7 -2
  288. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -1
  289. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +8 -3
  290. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +2 -0
  291. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +19 -0
  292. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -1
  293. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +1 -1
  294. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts +5 -0
  295. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts.map +1 -0
  296. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.js +22 -0
  297. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts +14 -0
  298. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts.map +1 -0
  299. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.js +13 -0
  300. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts +17 -0
  301. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts.map +1 -0
  302. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.js +16 -0
  303. package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts +15 -0
  304. package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts.map +1 -0
  305. package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.js +16 -0
  306. package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts +23 -0
  307. package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts.map +1 -0
  308. package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.js +28 -0
  309. package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts +2 -0
  310. package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts.map +1 -0
  311. package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.js +13 -0
  312. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +10 -5
  313. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -1
  314. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +15 -6
  315. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +6 -1
  316. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -1
  317. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +38 -1
  318. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
  319. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +4 -3
  320. package/src/shade/renderer/loader/gltf/load_gltf.d.ts.map +1 -1
  321. package/src/shade/renderer/loader/gltf/load_gltf.js +0 -19
  322. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  323. package/src/shade/renderer/material/chunk_material_draw_side.d.ts +14 -0
  324. package/src/shade/renderer/material/chunk_material_draw_side.d.ts.map +1 -0
  325. package/src/shade/renderer/material/chunk_material_draw_side.js +34 -0
  326. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  327. package/src/shade/renderer/material/standard/fragment_gbuffer.js +8 -1
  328. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  329. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +6 -3
  330. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  331. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +6 -3
  332. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
  333. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +13 -1
  334. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  335. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts +19 -5
  336. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts.map +1 -1
  337. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +23 -5
  338. package/src/shade/renderer/rasterize/bucket/filter_materials_by_bucket.d.ts.map +1 -1
  339. package/src/shade/renderer/rasterize/bucket/filter_materials_by_bucket.js +12 -5
  340. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  341. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +12 -4
  342. package/src/shade/renderer/rasterize/bucket/rasterization_opaque_buckets.d.ts +22 -0
  343. package/src/shade/renderer/rasterize/bucket/rasterization_opaque_buckets.d.ts.map +1 -0
  344. package/src/shade/renderer/rasterize/bucket/rasterization_opaque_buckets.js +36 -0
  345. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +2 -0
  346. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
  347. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +58 -57
  348. package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts +15 -0
  349. package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts.map +1 -0
  350. package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.js +35 -0
  351. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
  352. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +3 -5
  353. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
  354. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +3 -4
  355. package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.d.ts +10 -1
  356. package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.d.ts.map +1 -1
  357. package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.js +38 -29
  358. package/src/shade/renderer/rasterize/expand/bucket/chunk_rasterization_material_bucket.d.ts +5 -0
  359. package/src/shade/renderer/rasterize/expand/bucket/chunk_rasterization_material_bucket.d.ts.map +1 -1
  360. package/src/shade/renderer/rasterize/expand/bucket/chunk_rasterization_material_bucket.js +63 -55
  361. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  362. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +3 -4
  363. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts.map +1 -1
  364. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.js +1 -0
  365. package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.d.ts.map +1 -1
  366. package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.js +7 -7
  367. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
  368. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +83 -78
  369. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
  370. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +44 -53
  371. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
  372. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.js +6 -2
  373. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
  374. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.js +6 -2
  375. package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.d.ts.map +1 -1
  376. package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.js +19 -2
  377. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +7 -4
  378. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  379. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +3 -2
  380. package/src/shade/renderer/rasterize/native/chunk_rasterize_triangle.d.ts.map +1 -1
  381. package/src/shade/renderer/rasterize/native/chunk_rasterize_triangle.js +15 -4
  382. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
  383. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_alpha_tested_pass_descriptor.js +16 -5
  384. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_pass_descriptor.d.ts.map +1 -1
  385. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_pass_descriptor.js +16 -5
  386. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
  387. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +2 -1
  388. package/src/shade/renderer/rasterize/native/rasterization_shader_resources.d.ts.map +1 -1
  389. package/src/shade/renderer/rasterize/native/rasterization_shader_resources.js +4 -0
  390. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
  391. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +16 -7
  392. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  393. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +85 -89
  394. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  395. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +28 -32
  396. package/src/shade/renderer/scene/GPUSceneContext.d.ts +22 -2
  397. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  398. package/src/shade/renderer/scene/GPUSceneContext.js +61 -4
  399. package/src/shade/renderer/scene/NODE3D_STRUCT.d.ts +19 -0
  400. package/src/shade/renderer/scene/NODE3D_STRUCT.d.ts.map +1 -1
  401. package/src/shade/renderer/scene/NODE3D_STRUCT.js +34 -0
  402. package/src/shade/renderer/scene/chunk_node3d_flags.d.ts +9 -0
  403. package/src/shade/renderer/scene/chunk_node3d_flags.d.ts.map +1 -0
  404. package/src/shade/renderer/scene/chunk_node3d_flags.js +23 -0
  405. package/src/shade/renderer/scene/chunk_scene_database_access.d.ts.map +1 -1
  406. package/src/shade/renderer/scene/chunk_scene_database_access.js +15 -1
  407. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
  408. package/src/shade/renderer/scene/rows/GPUSceneRows.js +9 -1
  409. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.d.ts +7 -0
  410. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.d.ts.map +1 -1
  411. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.js +16 -4
  412. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.d.ts +12 -0
  413. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.d.ts.map +1 -0
  414. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.js +18 -0
  415. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_triangle_list_reverse_winding.d.ts +24 -0
  416. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_triangle_list_reverse_winding.d.ts.map +1 -0
  417. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_triangle_list_reverse_winding.js +33 -0
  418. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  419. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +92 -16
  420. package/src/shade/renderer/view/GPUViewContext.d.ts +5 -0
  421. package/src/shade/renderer/view/GPUViewContext.d.ts.map +1 -1
  422. package/src/shade/renderer/view/GPUViewContext.js +21 -0
  423. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  424. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +74 -3
  425. package/src/shade/playground/vgeo_viewer/README.md +0 -150
  426. package/src/shade/playground/vgeo_viewer/cut_geometry.js +0 -460
  427. package/src/shade/playground/vgeo_viewer/index.html +0 -77
  428. package/src/shade/playground/vgeo_viewer/main.js +0 -1343
  429. package/src/shade/playground/vgeo_viewer/select_cut.js +0 -481
  430. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts +0 -258
  431. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts.map +0 -1
  432. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +0 -723
  433. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts +0 -49
  434. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts.map +0 -1
  435. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +0 -50
  436. package/src/shade/renderer/loader/gltf/fix_up_material_sides.js +0 -109
  437. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.js +0 -78
  438. package/src/shade/renderer/rasterize/expand/shader_filter_triangle_by_material_side.js +0 -100
  439. package/src/shade/renderer/rasterize/forward/chunk_material_side_should_draw.js +0 -26
  440. package/src/shade/renderer/shader/chunk/jobs/NOTES.md +0 -47
  441. package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.d.ts +0 -3
  442. package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.d.ts.map +0 -1
  443. package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.js +0 -102
  444. /package/src/shade/renderer/geometry/virtual/build/{VGeoLevel.js → level/VGeoLevel.js} +0 -0
  445. /package/src/shade/renderer/geometry/virtual/build/{VGeoLevelOptions.js → level/VGeoLevelOptions.js} +0 -0
  446. /package/src/shade/renderer/geometry/virtual/build/{VGeoLevelSummary.js → level/VGeoLevelSummary.js} +0 -0
  447. /package/src/shade/renderer/geometry/virtual/build/{vgeo_graph_components.js → partition/vgeo_graph_components.js} +0 -0
  448. /package/src/shade/renderer/geometry/virtual/build/{VGeoGatheredFaces.js → submesh/VGeoGatheredFaces.js} +0 -0
  449. /package/src/shade/renderer/geometry/virtual/build/{VGeoSubmesh.js → submesh/VGeoSubmesh.js} +0 -0
@@ -1,10 +1,15 @@
1
1
  import { assert } from "../../../../../core/assert.js";
2
2
  import { graph_read_buffer } from "../../../buffer/graph_read_buffer.js";
3
- import { VGeoPageWant } from "../format/read/VGeoPageWant.js";
3
+ import { VGEO_CUT_STAT } from "./layout/VGEO_CUT_STAT.js";
4
4
  import { VGEO_CUT_STAT_COUNT } from "./layout/VGEO_CUT_STAT_COUNT.js";
5
5
  import { VGEO_FEEDBACK_OFFSET } from "./layout/VGEO_FEEDBACK_OFFSET.js";
6
- import { VGEO_PAGE_ROW_OFFSET } from "./layout/VGEO_PAGE_ROW_OFFSET.js";
7
- import { VGEO_WANT_WORDS } from "./layout/VGEO_WANT_WORDS.js";
6
+
7
+ /**
8
+ * @typedef {import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
9
+ * @typedef {import("./GPUVirtualGeometryRuntime.js").GPUVirtualGeometryRuntime} GPUVirtualGeometryRuntime
10
+ * @typedef {import("./VGeoResidency.js").VGeoResidency} VGeoResidency
11
+ * @typedef {import("./cut/vgeo_cut_feedback_layout.js").vgeo_cut_feedback_layout} vgeo_cut_feedback_layout
12
+ */
8
13
 
9
14
  /**
10
15
  * The other half of the loop: what the cut saw, coming back to the host.
@@ -14,20 +19,11 @@ import { VGEO_WANT_WORDS } from "./layout/VGEO_WANT_WORDS.js";
14
19
  * feedback is skipped entirely** when saturated. A loop that insisted on a reading every frame
15
20
  * would stall the frame it was reading, which is the failure the cap exists to prevent.
16
21
  *
17
- * What comes back is two lists and a counter block:
18
- *
19
- * - **touches** — page rows the cut drew from. They go to the VRAM pool's LRU and to
20
- * `VGeoResidencyManager`'s, which is design §6's touch-LRU at both tiers. Not last-*wanted*:
21
- * stamping at fetch time freezes the stamp of exactly what is on screen and evicts it.
22
- * - **wants** — pages a clamped cluster could not reach, each naming the page it was discovered
23
- * *through*. That second half is what resolves the byte range without a directory, and it is
24
- * also the page format §10 asks to be pinned while its child is in flight.
25
- *
26
- * A want resolves to one of two very different things, and telling them apart is this class's real
27
- * work. A page already in RAM is a **VRAM install** and no fetch at all — the bytes are here and
28
- * the cut simply has not been given them. A page not in RAM is a fetch, handed to the residency
29
- * manager with its priority so that it competes globally against every other asset's wants rather
30
- * than within whichever reader asked first.
22
+ * This class is the transport and nothing else: it schedules the readback while the graph is still
23
+ * being built, closes the frame's own layout and frame number over it, keeps the counters the
24
+ * kernel wrote, and hands the words to {@link VGeoResidency.apply}. What a touch or a want means —
25
+ * which tier it lands on, what it costs, what is fetched and what is refused — is the residency's,
26
+ * in one place for both tiers (RUNTIME_PLAN_2026_09_14 §4.7).
31
27
  *
32
28
  * @author Alex Goldring
33
29
  * @copyright Company Named Limited (c) 2026
@@ -39,7 +35,7 @@ export class VGeoFeedbackLoop {
39
35
  #runtime;
40
36
 
41
37
  /**
42
- * @type {VGeoResidencyManager}
38
+ * @type {VGeoResidency}
43
39
  */
44
40
  #residency;
45
41
 
@@ -53,11 +49,6 @@ export class VGeoFeedbackLoop {
53
49
  */
54
50
  #max_in_flight;
55
51
 
56
- /**
57
- * @type {number}
58
- */
59
- #install_budget_bytes;
60
-
61
52
  /**
62
53
  * @type {number}
63
54
  */
@@ -74,121 +65,27 @@ export class VGeoFeedbackLoop {
74
65
  */
75
66
  #stats = new Uint32Array(VGEO_CUT_STAT_COUNT);
76
67
 
77
- /**
78
- * @type {number}
79
- */
80
- #last_want_count = 0;
81
-
82
- /**
83
- * @type {number}
84
- */
85
- #last_touch_count = 0;
86
-
87
- /**
88
- * Page indices this loop has asked for and not yet heard back about, per reader.
89
- *
90
- * A page stays wanted for as long as it is missing, so the same want arrives every frame until
91
- * the fetch lands. Without this the shared `ConcurrencyGate` accumulates one closure per frame
92
- * per wanted page and the RAM budget is charged once per frame for the same bytes.
93
- *
94
- * @type {Map<VGeoContainerReader, Set<number>>}
95
- */
96
- #in_flight_pages = new Map();
97
-
98
- /**
99
- * One per batch of fetches still running, so {@link abort} can stop all of them.
100
- * @type {Set<AbortController>}
101
- */
102
- #controllers = new Set();
103
-
104
- /**
105
- * @type {number}
106
- */
107
- #max_wants_per_frame;
108
-
109
- /**
110
- * @type {number}
111
- */
112
- #deduped_wants = 0;
113
-
114
- /**
115
- * @type {number}
116
- */
117
- #dropped_wants = 0;
118
-
119
- /**
120
- * @type {number}
121
- */
122
- #failed_batches = 0;
123
-
124
- /**
125
- * Touches and wants naming a page row that was re-used between the cut and this reading.
126
- * @type {number}
127
- */
128
- #stale_records = 0;
129
-
130
68
  /**
131
69
  * @param {Object} options
132
70
  * @param {GPUVirtualGeometryRuntime} options.runtime
133
- * @param {VGeoResidencyManager} options.residency the RAM tier's budget owner
134
- * @param {number} [options.max_in_flight] readbacks that may be outstanding at once
135
- * @param {number} [options.install_budget_bytes] decoded page bytes promoted to VRAM per frame
136
- * @param {number} [options.max_wants_per_frame] pages one frame may newly ask to fetch, across
137
- * every reader — see {@link #dispatch_frame}, which is where the "across every reader" is
138
- * enforced; the rest are dropped and asked for again next frame, which is what a want is
139
- * for
71
+ * @param {VGeoResidency} options.residency both tiers' owner
72
+ * @param {number} [options.max_in_flight] readbacks that may be outstanding at once; defaults
73
+ * to the residency's option
140
74
  */
141
- constructor({
142
- runtime,
143
- residency,
144
- max_in_flight = 2,
145
- install_budget_bytes = 8 * 1024 * 1024,
146
- max_wants_per_frame = 32,
147
- }) {
75
+ constructor({ runtime, residency, max_in_flight = undefined }) {
148
76
  assert.defined(runtime, 'runtime');
149
77
  assert.defined(residency, 'residency');
150
78
 
151
79
  this.#runtime = runtime;
152
80
  this.#residency = residency;
153
- this.#max_in_flight = max_in_flight;
154
- this.#install_budget_bytes = install_budget_bytes;
155
- this.#max_wants_per_frame = max_wants_per_frame;
81
+ this.#max_in_flight = max_in_flight ?? residency.options.max_readbacks_in_flight;
156
82
  }
157
83
 
158
84
  /**
159
- * Feedback records naming a page row that had been re-used by the time the reading landed.
160
- * @returns {number}
85
+ * @returns {VGeoResidency}
161
86
  */
162
- get stale_record_count() {
163
- return this.#stale_records;
164
- }
165
-
166
- /**
167
- * Wants this loop did not re-submit because the page was already being fetched.
168
- * @returns {number}
169
- */
170
- get deduped_want_count() {
171
- return this.#deduped_wants;
172
- }
173
-
174
- /**
175
- * Wants past this frame's fetch limit. Not a failure — the next cut asks again.
176
- * @returns {number}
177
- */
178
- get dropped_want_count() {
179
- return this.#dropped_wants;
180
- }
181
-
182
- /**
183
- * Batches every page of which the reader quarantined, plus any that rejected outright.
184
- *
185
- * A reader that has stopped answering is the one streaming failure a host can do something
186
- * about, and it is the one thing a per-page quarantine cannot say on its own.
187
- *
188
- * @returns {number}
189
- */
190
- get failed_batch_count() {
191
- return this.#failed_batches;
87
+ get residency() {
88
+ return this.#residency;
192
89
  }
193
90
 
194
91
  /**
@@ -221,14 +118,22 @@ export class VGeoFeedbackLoop {
221
118
  * @returns {number}
222
119
  */
223
120
  get last_want_count() {
224
- return this.#last_want_count;
121
+ return this.#residency.last_want_count;
225
122
  }
226
123
 
227
124
  /**
228
125
  * @returns {number}
229
126
  */
230
127
  get last_touch_count() {
231
- return this.#last_touch_count;
128
+ return this.#residency.last_touch_count;
129
+ }
130
+
131
+ /**
132
+ * Records naming a page row that was refilled between the cut and the reading.
133
+ * @returns {number}
134
+ */
135
+ get stale_record_count() {
136
+ return this.#residency.stale_record_count;
232
137
  }
233
138
 
234
139
  /**
@@ -240,20 +145,6 @@ export class VGeoFeedbackLoop {
240
145
  read(graph) {
241
146
  assert.defined(graph, 'graph');
242
147
 
243
- /*
244
- The RAM tier's clock, moved here rather than left to the host. `advance_frame` is what
245
- carries the protect window forward, and without it `evict_to_budget` protects everything
246
- and never drops a page — so the RAM tier is unbounded. Its only non-spec caller was the
247
- playground (REVIEW_LEDGER M12), which is to say that in any real host the second tier of a
248
- three-tier design was doing nothing at all.
249
-
250
- Before the early returns below on purpose: a frame whose feedback is skipped is still a
251
- frame, and a clock that only advanced on the frames the readback kept up with would make
252
- the protect window a function of readback latency.
253
- */
254
- this.#residency.advance_frame();
255
- this.#residency.evict_to_budget();
256
-
257
148
  const feedback = this.#runtime.feedback;
258
149
 
259
150
  if (feedback === -1) {
@@ -268,27 +159,27 @@ export class VGeoFeedbackLoop {
268
159
 
269
160
  /*
270
161
  Closed over, not looked up again when the reading lands. `begin_frame` recomputes the
271
- layout every frame out of the page-row high-water mark and the lookup word count, both of
272
- which move as pages install — so a readback that lands a frame or two later and asked the
273
- runtime for "the" layout would decode this frame's bytes with a later frame's bases, and
274
- read wants and touches out of the middle of the stamp region (REVIEW_LEDGER C5).
162
+ layout every frame out of the page-row high-water mark, which moves as pages install — so a
163
+ readback that lands a frame or two later and asked the runtime for "the" layout would
164
+ decode this frame's bytes with a later frame's bases (REVIEW_LEDGER C5).
275
165
  */
276
166
  const layout = this.#runtime.feedback_layout;
277
167
 
278
168
  /*
279
- And the generation of every page row that exists right now. A row is reused the moment it
280
- is freed and this reading is at least a frame behind the cut that produced it, so a touch
281
- or a want naming row 7 may be naming the page that *was* in row 7. Comparing the generation
282
- is what tells the two apart (REVIEW_LEDGER M10).
169
+ And the frame this reading is about. A row is reused the moment it is freed and this
170
+ reading is at least a frame behind the cut that produced it, so a touch or a want naming
171
+ row 7 may be naming the page that *was* in row 7 (REVIEW_LEDGER M10). The pool stamps every
172
+ row with the frame whose flush publishes its occupant, and the residency compares that per
173
+ record against this number.
283
174
  */
284
- const generations = this.#snapshot_generations();
175
+ const reading_frame = this.#runtime.pool.frame;
285
176
 
286
177
  this.#in_flight++;
287
178
 
288
179
  graph_read_buffer({ graph, buffer: feedback, offset: 0, size: layout.word_count * 4 })
289
180
  .then(reference => {
290
181
  try {
291
- this.#apply(new Uint32Array(reference.getValue()), layout, generations);
182
+ this.#apply(new Uint32Array(reference.getValue()), layout, reading_frame);
292
183
  } finally {
293
184
  reference.release();
294
185
  }
@@ -306,365 +197,42 @@ export class VGeoFeedbackLoop {
306
197
  return true;
307
198
  }
308
199
 
309
- /**
310
- * @returns {Uint32Array} one generation per page row that could appear in this frame's feedback
311
- */
312
- #snapshot_generations() {
313
- const tables = this.#runtime.pool.tables;
314
-
315
- const count = this.#runtime.pool.page_row_capacity;
316
-
317
- const generations = new Uint32Array(count);
318
-
319
- for (let row = 0; row < count; row++) {
320
- generations[row] = tables.generation_of(row);
321
- }
322
-
323
- return generations;
324
- }
325
-
326
- /**
327
- * Whether a page row still holds the page it held when the cut ran.
328
- *
329
- * @param {number} page_row
330
- * @param {Uint32Array} generations
331
- * @returns {boolean}
332
- */
333
- #still_the_same_page(page_row, generations) {
334
- if (page_row >= generations.length) {
335
- // a row that did not exist when the graph was built cannot be one this cut named
336
- return false;
337
- }
338
-
339
- return this.#runtime.pool.tables.generation_of(page_row) === generations[page_row];
340
- }
341
-
342
200
  /**
343
201
  * @param {Uint32Array} words
344
202
  * @param {ReturnType<vgeo_cut_feedback_layout>} layout the frame's own, not the current one
345
- * @param {Uint32Array} generations per page row, as of the frame this reading is about
203
+ * @param {number} reading_frame the frame this reading is about
346
204
  */
347
- #apply(words, layout, generations) {
348
- const pool = this.#runtime.pool;
349
-
205
+ #apply(words, layout, reading_frame) {
350
206
  for (let i = 0; i < VGEO_CUT_STAT_COUNT; i++) {
351
207
  this.#stats[i] = words[VGEO_FEEDBACK_OFFSET.STATS + i];
352
208
  }
353
209
 
354
210
  /*
355
- Clamped, because the count is an `atomicAdd` that ran past the capacity the kernel then
356
- refused to write at. Reading it unclamped would read the words after the list, which are
357
- whatever the pool's transient buffer held before this frame.
358
- */
359
- const touch_count = Math.min(
360
- words[VGEO_FEEDBACK_OFFSET.TOUCH_COUNT], layout.word_count - layout.touch_base
361
- );
362
-
363
- this.#last_touch_count = touch_count;
364
- this.#last_want_count = Math.min(
365
- words[VGEO_FEEDBACK_OFFSET.WANT_COUNT],
366
- Math.floor((layout.touch_base - layout.want_base) / VGEO_WANT_WORDS)
367
- );
368
-
369
- for (let i = 0; i < touch_count; i++) {
370
- const page_row = words[layout.touch_base + i];
371
-
372
- const entry = pool.entry_of(page_row);
373
-
374
- if (entry === undefined) {
375
- // evicted between the cut and the reading; the stamp it would have taken is moot
376
- continue;
377
- }
378
-
379
- if (!this.#still_the_same_page(page_row, generations)) {
380
- /*
381
- Evicted *and refilled* in between. Stamping now would tell both tiers' LRU that a
382
- page nobody has drawn is the hottest thing in the cache, and it would do it at
383
- exactly the moment a page was streaming in.
384
- */
385
- this.#stale_records++;
386
-
387
- continue;
388
- }
389
-
390
- pool.touch(page_row);
391
-
392
- this.#residency.touch(
393
- entry.reader, pool.tables.page_field(page_row, VGEO_PAGE_ROW_OFFSET.PAGE_INDEX)
394
- );
395
- }
396
-
397
- /**
398
- * Wants that need bytes, per reader — the residency manager takes them a reader at a time
399
- * because a reader is what owns a fetch, and orders them globally because a priority in
400
- * pixels of error is comparable across assets by construction.
401
- * @type {Map<VGeoContainerReader, VGeoPageWant[]>}
402
- */
403
- const fetches = new Map();
404
-
405
- let promoted = 0;
406
-
407
- for (let i = 0; i < this.#last_want_count; i++) {
408
- const base = layout.want_base + i * VGEO_WANT_WORDS;
409
-
410
- const source_row = words[base];
411
- const child_ref = words[base + 1];
412
- const child_page_index = words[base + 2];
413
- const priority = new Float32Array(new Uint32Array([words[base + 3]]).buffer)[0];
414
-
415
- const entry = pool.entry_of(source_row);
416
-
417
- if (entry === undefined) {
418
- continue;
419
- }
420
-
421
- if (!this.#still_the_same_page(source_row, generations)) {
422
- /*
423
- The row was reused between the cut and this reading, so the page index below and
424
- the byte range the child table would give come from two different pages — a fetch
425
- aimed at a page nobody asked for, charged to the RAM budget, at the priority of a
426
- cluster in an unrelated part of the asset.
427
- */
428
- this.#stale_records++;
429
-
430
- continue;
431
- }
432
-
433
- const reader = entry.reader;
434
-
435
- const source_index = pool.tables.page_field(source_row, VGEO_PAGE_ROW_OFFSET.PAGE_INDEX);
436
-
437
- const source = reader.page(source_index);
438
-
439
- if (source === undefined || child_ref >= source.child_page_index.length) {
440
- continue;
441
- }
442
-
443
- if (reader.is_resident(child_page_index)) {
444
- /*
445
- The bytes are already in RAM, so this is not a fetch at all — the cut is clamping
446
- because the page has not been promoted to VRAM yet. Budgeted per frame, because a
447
- camera that suddenly wants a hundred pages should get them over several frames
448
- rather than in one hitch.
449
- */
450
- if (promoted < this.#install_budget_bytes) {
451
- if (pool.install(reader, child_page_index) !== -1) {
452
- promoted += source.child_decoded_size[child_ref];
453
- }
454
- }
455
-
456
- continue;
457
- }
458
-
459
- const want = new VGeoPageWant();
460
-
461
- want.page_index = child_page_index;
462
- want.frame_offset = source.child_frame_offset[child_ref];
463
- want.fetch_size = source.child_fetch_size[child_ref];
464
- want.decoded_size = source.child_decoded_size[child_ref];
465
- want.priority = priority;
466
- want.reference_count = 1;
467
-
468
- const list = fetches.get(reader) ?? [];
469
-
470
- list.push(want);
471
-
472
- fetches.set(reader, list);
473
- }
474
-
475
- this.#dispatch_frame(fetches);
476
- }
477
-
478
- /**
479
- * One frame's fetches: deduped against what is in flight, ranked across every reader, and cut
480
- * to the frame's limit.
481
- *
482
- * **Across every reader, which is what the option has always said and not what it did.**
483
- * `max_wants_per_frame` was applied inside {@link #dispatch_wants}, once per reader, so a frame
484
- * seeing eight streaming assets issued eight times the limit — the shape
485
- * `VGeoResidencyManager`'s own doc records being measured at 48 concurrent range requests
486
- * against a cap of 6, and the reason its gate is shared. One frame, one budget.
487
- *
488
- * Ranked across readers for the same reason the gate is shared: a want's priority is pixels of
489
- * projected error past the threshold, which is comparable across assets by construction. So the
490
- * frame's budget goes to the worst coarseness on screen wherever it came from, rather than to
491
- * whichever reader this frame's touch list happened to name first.
492
- *
493
- * @param {Map<VGeoContainerReader, VGeoPageWant[]>} fetches
494
- */
495
- #dispatch_frame(fetches) {
496
- /**
497
- * @type {{reader: VGeoContainerReader, want: VGeoPageWant}[]}
498
- */
499
- const fresh = [];
500
-
501
- for (const [reader, wants] of fetches) {
502
- const in_flight = this.#in_flight_of(reader);
503
-
504
- for (const want of wants) {
505
- if (in_flight.has(want.page_index)) {
506
- this.#deduped_wants++;
507
-
508
- continue;
509
- }
510
-
511
- fresh.push({ reader, want });
512
- }
513
- }
514
-
515
- if (fresh.length === 0) {
516
- return;
517
- }
518
-
519
- fresh.sort((a, b) => b.want.priority - a.want.priority);
520
-
521
- const batch = fresh.slice(0, this.#max_wants_per_frame);
522
-
523
- this.#dropped_wants += fresh.length - batch.length;
524
-
525
- /**
526
- * Back into per-reader lists, because a reader is what owns a fetch.
527
- * @type {Map<VGeoContainerReader, VGeoPageWant[]>}
528
- */
529
- const by_reader = new Map();
530
-
531
- for (const { reader, want } of batch) {
532
- const list = by_reader.get(reader) ?? [];
533
-
534
- list.push(want);
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]);
535
218
 
536
- by_reader.set(reader, list);
537
- }
538
-
539
- for (const [reader, wants] of by_reader) {
540
- this.#dispatch_wants(reader, wants);
541
- }
219
+ this.#residency.apply(words, layout, reading_frame);
542
220
  }
543
221
 
544
222
  /**
545
- * @param {VGeoContainerReader} reader
546
- * @returns {Set<number>} page indices this loop has asked that reader for and not heard back
547
- */
548
- #in_flight_of(reader) {
549
- let in_flight = this.#in_flight_pages.get(reader);
550
-
551
- if (in_flight === undefined) {
552
- in_flight = new Set();
553
-
554
- this.#in_flight_pages.set(reader, in_flight);
555
- }
556
-
557
- return in_flight;
558
- }
559
-
560
- /**
561
- * Hand one reader's share of this frame's batch to the residency manager.
562
- *
563
- * This was `install_wants(...).catch(() => {})` and nothing else, which costs three things that
564
- * compound rather than three separate ones. A page still wanted while its fetch is in flight is
565
- * re-submitted **every frame**, so the shared `ConcurrencyGate` accumulates one stale closure
566
- * per frame per wanted page and the RAM budget is charged for the same page over and over. A
567
- * batch that is still running when the next arrives has no way to be told to stop. And an empty
568
- * catch turns a reader that has quarantined every page it was asked for into silence
569
- * (REVIEW_LEDGER M11).
570
- *
571
- * So: a page already in flight is not asked for again, the whole batch carries one
572
- * `AbortSignal` that {@link abort} can pull, and a failure is counted and reported once rather
573
- * than swallowed once per frame. The dedup and the frame's limit are {@link #dispatch_frame}'s,
574
- * one level up, because both are properties of the frame rather than of a reader.
575
- *
576
- * @param {VGeoContainerReader} reader
577
- * @param {VGeoPageWant[]} batch already deduped and inside this frame's limit
578
- */
579
- #dispatch_wants(reader, batch) {
580
- const in_flight = this.#in_flight_of(reader);
581
-
582
- for (const want of batch) {
583
- in_flight.add(want.page_index);
584
- }
585
-
586
- const controller = new AbortController();
587
-
588
- this.#controllers.add(controller);
589
-
590
- this.#residency.install_wants(reader, batch, batch.length, controller.signal)
591
- .then(() => {
592
- if (controller.signal.aborted) {
593
- return;
594
- }
595
-
596
- /*
597
- A failed fetch does not come back as a rejection. `VGeoResidencyManager` catches it
598
- per page — the cut stands without any one page, which is the whole point of a
599
- clamped cut — so a `.catch` here sees only a programming error, and the campaign
600
- closed M11 with the reporting on exactly that branch. A reader that has quarantined
601
- every page asked of it was therefore still silent (re-review 2026-09-12).
602
-
603
- The reader's quarantine is where the fact lives, so that is what is read. Every
604
- page of the batch quarantined is an asset that cannot be streamed at all, which is
605
- the condition worth one line in the console; a page or two is ordinary attrition
606
- and is on `VGeoResidencyManager.quarantined_page_count` for whoever is watching.
607
- */
608
- let quarantined = 0;
609
-
610
- for (const want of batch) {
611
- if (reader.is_quarantined(want.page_index)) {
612
- quarantined++;
613
- }
614
- }
615
-
616
- if (quarantined < batch.length) {
617
- return;
618
- }
619
-
620
- this.#failed_batches++;
621
-
622
- // once per batch, not once per frame per page: the dedup one level up is what makes
623
- // that difference, and a reader that has quarantined everything asked of it is a
624
- // fact somebody has to be able to see
625
- console.warn(
626
- `vgeo: every one of ${batch.length} page fetches was quarantined`
627
- + ` by ${reader.name ?? 'a reader'}`
628
- );
629
- })
630
- .catch(error => {
631
- if (controller.signal.aborted) {
632
- return;
633
- }
634
-
635
- this.#failed_batches++;
636
-
637
- console.warn('vgeo: a batch of page fetches failed', error);
638
- })
639
- .finally(() => {
640
- this.#controllers.delete(controller);
641
-
642
- for (const want of batch) {
643
- in_flight.delete(want.page_index);
644
- }
645
- });
646
- }
647
-
648
- /**
649
- * Stop every fetch this loop started.
223
+ * Stop every fetch the residency has on the wire.
650
224
  *
651
225
  * @returns {void}
652
226
  */
653
227
  abort() {
654
- for (const controller of Array.from(this.#controllers)) {
655
- controller.abort();
656
- }
657
-
658
- this.#controllers.clear();
659
- this.#in_flight_pages.clear();
228
+ this.#residency.abort();
660
229
  }
661
230
 
662
231
  /**
663
232
  * Give up on this loop: the same as {@link abort}, under the name a host tears things down by.
664
233
  *
665
234
  * The loop owns no device resource, so there is nothing else to release — what it owns is
666
- * outstanding *work*, and the reason to have this verb at all is that `abort` reads like a
667
- * transient control ("stop what is in flight, carry on") while a teardown is final.
235
+ * outstanding *work*.
668
236
  *
669
237
  * @returns {void}
670
238
  */