@woosh/meep-engine 3.26.0 → 3.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/package.json +1 -1
  2. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +542 -0
  3. package/src/core/binary/lz4/LZ4_LEVEL.d.ts +33 -0
  4. package/src/core/binary/lz4/LZ4_LEVEL.d.ts.map +1 -0
  5. package/src/core/binary/lz4/LZ4_LEVEL.js +32 -0
  6. package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts +33 -0
  7. package/src/core/binary/lz4/lz4_compress_block_at_level.d.ts.map +1 -0
  8. package/src/core/binary/lz4/lz4_compress_block_at_level.js +47 -0
  9. package/src/core/binary/lz4/lz4_compress_block_hc.d.ts +40 -0
  10. package/src/core/binary/lz4/lz4_compress_block_hc.d.ts.map +1 -0
  11. package/src/core/binary/lz4/lz4_compress_block_hc.js +1382 -0
  12. package/src/core/binary/lz4/lz4_decompress_block.d.ts +2 -1
  13. package/src/core/binary/lz4/lz4_decompress_block.d.ts.map +1 -1
  14. package/src/core/binary/lz4/lz4_decompress_block.js +31 -6
  15. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +14 -7
  16. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
  17. package/src/core/geom/3d/shape/HeightMapShape3D.js +87 -78
  18. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  19. package/src/shade/playground/vgeo_runtime/README.md +167 -22
  20. package/src/shade/playground/vgeo_runtime/index.html +112 -62
  21. package/src/shade/playground/vgeo_runtime/main.js +660 -83
  22. package/src/shade/playground/vgeo_viewer/sample_asset.d.ts.map +1 -1
  23. package/src/shade/playground/vgeo_viewer/sample_asset.js +19 -2
  24. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +11 -0
  25. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  26. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +16 -8
  27. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  28. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +16 -11
  29. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +73 -5
  30. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +26 -15
  31. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +5 -3
  32. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +18 -0
  33. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  34. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +20 -0
  35. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
  36. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +56 -9
  37. package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts.map +1 -1
  38. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +1 -0
  39. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +22 -0
  40. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
  41. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +24 -0
  42. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts +12 -0
  43. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.d.ts.map +1 -1
  44. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +13 -0
  45. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts +8 -1
  46. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.d.ts.map +1 -1
  47. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +11 -3
  48. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts +9 -0
  49. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.d.ts.map +1 -1
  50. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +10 -1
  51. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts +18 -0
  52. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.d.ts.map +1 -0
  53. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_ENTRY_COUNT.js +17 -0
  54. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts +8 -0
  55. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.d.ts.map +1 -0
  56. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_PARENT_REF.js +7 -0
  57. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.d.ts +3 -0
  58. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -0
  59. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts +14 -0
  60. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.d.ts.map +1 -0
  61. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_ENTRY_SIZE.js +13 -0
  62. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts +11 -0
  63. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.d.ts.map +1 -0
  64. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PARENT_PAGE_ENTRY_SIZE.js +10 -0
  65. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +20 -0
  66. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
  67. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +20 -2
  68. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +4 -0
  69. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
  70. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +4 -0
  71. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +29 -3
  72. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
  73. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +81 -122
  74. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +40 -0
  75. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
  76. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +44 -0
  77. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts +69 -0
  78. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.d.ts.map +1 -0
  79. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageFetcherCore.js +236 -0
  80. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +14 -0
  81. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
  82. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +15 -0
  83. package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts +31 -0
  84. package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.d.ts.map +1 -0
  85. package/src/shade/renderer/geometry/virtual/format/read/vgeo_byte_source_from_descriptor.js +32 -0
  86. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +10 -0
  87. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
  88. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +21 -1
  89. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts +15 -0
  90. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.d.ts.map +1 -0
  91. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_transfer.js +84 -0
  92. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts +22 -0
  93. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.d.ts.map +1 -0
  94. package/src/shade/renderer/geometry/virtual/format/read/vgeo_page_worker_serve.js +96 -0
  95. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  96. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +55 -0
  97. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  98. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +202 -13
  99. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  100. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +147 -10
  101. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +637 -0
  102. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +33 -36
  103. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -1
  104. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +109 -193
  105. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +58 -28
  106. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
  107. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +77 -105
  108. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +37 -0
  109. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +105 -22
  110. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +548 -0
  111. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +29 -50
  112. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -1
  113. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +47 -489
  114. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts +84 -0
  115. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts.map +1 -0
  116. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js +393 -0
  117. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts +234 -0
  118. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts.map +1 -0
  119. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js +1363 -0
  120. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts +81 -0
  121. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.d.ts.map +1 -0
  122. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidencyOptions.js +89 -0
  123. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +53 -34
  124. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -1
  125. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +407 -124
  126. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts +100 -0
  127. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts.map +1 -0
  128. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.js +219 -0
  129. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts +17 -0
  130. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.d.ts.map +1 -0
  131. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_EXPAND.js +47 -0
  132. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts +20 -0
  133. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.d.ts.map +1 -0
  134. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_COARSEN.js +19 -0
  135. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -1
  136. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +30 -12
  137. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -1
  138. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +15 -0
  139. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -1
  140. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +18 -1
  141. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -1
  142. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +5 -15
  143. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts +3 -0
  144. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.d.ts.map +1 -0
  145. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_remainder.js +77 -0
  146. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts +3 -0
  147. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts.map +1 -0
  148. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.js +186 -0
  149. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -1
  150. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +20 -8
  151. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -1
  152. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +580 -188
  153. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +15 -18
  154. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -1
  155. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +19 -28
  156. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
  157. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +45 -25
  158. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +1 -0
  159. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +11 -0
  160. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +1 -1
  161. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +0 -1
  162. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +12 -10
  163. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +1 -0
  164. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +8 -0
  165. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +7 -2
  166. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -1
  167. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +8 -3
  168. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +2 -0
  169. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +19 -0
  170. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -1
  171. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +1 -1
  172. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts +5 -0
  173. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.d.ts.map +1 -0
  174. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_OFFSET.js +22 -0
  175. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts +14 -0
  176. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.d.ts.map +1 -0
  177. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PARENT_ROW_WORDS.js +13 -0
  178. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts +17 -0
  179. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.d.ts.map +1 -0
  180. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_PARENT_BIT.js +16 -0
  181. package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts +15 -0
  182. package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.d.ts.map +1 -0
  183. package/src/shade/renderer/geometry/virtual/runtime/make_vgeo_page_worker.js +16 -0
  184. package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts +23 -0
  185. package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.d.ts.map +1 -0
  186. package/src/shade/renderer/geometry/virtual/runtime/vgeo_frontier_words.js +28 -0
  187. package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts +2 -0
  188. package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.d.ts.map +1 -0
  189. package/src/shade/renderer/geometry/virtual/runtime/vgeo_page.worker.js +13 -0
  190. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +10 -5
  191. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -1
  192. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +15 -6
  193. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +6 -1
  194. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -1
  195. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +38 -1
  196. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.d.ts.map +1 -1
  197. package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_evict.js +4 -3
  198. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  199. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  200. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +6 -3
  201. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  202. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +6 -3
  203. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  204. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  205. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +12 -4
  206. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +2 -0
  207. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
  208. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +58 -57
  209. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.d.ts.map +1 -1
  210. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_mesh_filter_2way.js +3 -5
  211. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.d.ts.map +1 -1
  212. package/src/shade/renderer/rasterize/cull/hzb/shader_hzb_meshlet_filter_1way_full.js +3 -4
  213. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.d.ts.map +1 -1
  214. package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_extract_bucket.js +3 -4
  215. package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.d.ts.map +1 -1
  216. package/src/shade/renderer/rasterize/expand/pass0/pass_mesh_cull.js +7 -7
  217. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
  218. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +83 -78
  219. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  220. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +7 -1
  221. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  222. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +7 -1
  223. package/src/shade/renderer/scene/GPUSceneContext.d.ts +22 -2
  224. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  225. package/src/shade/renderer/scene/GPUSceneContext.js +59 -4
  226. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  227. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +92 -16
  228. package/src/shade/renderer/view/GPUViewContext.d.ts +5 -0
  229. package/src/shade/renderer/view/GPUViewContext.d.ts.map +1 -1
  230. package/src/shade/renderer/view/GPUViewContext.js +21 -0
  231. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  232. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +74 -3
  233. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +0 -723
  234. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +0 -50
  235. package/src/shade/renderer/shader/chunk/jobs/NOTES.md +0 -47
  236. package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.js +0 -102
@@ -1,3 +1,7 @@
1
+ /**
2
+ * @typedef {import("./GPUVirtualGeometryPool.js").GPUVirtualGeometryPool} GPUVirtualGeometryPool
3
+ * @typedef {import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
4
+ */
1
5
  /**
2
6
  * What one frame of virtual geometry needs that is not a page: the threshold, the feedback buffer
3
7
  * every view writes into, and the parameters every pass reads.
@@ -19,27 +23,25 @@ export class GPUVirtualGeometryRuntime {
19
23
  /**
20
24
  * @param {Object} options
21
25
  * @param {GPUVirtualGeometryPool} options.pool
22
- * @param {GPUDevice} options.device
23
26
  * @param {number} [options.want_capacity] pages one frame may ask for, across every view
24
- * @param {number} [options.touch_capacity] page rows one frame may report drawing from
25
27
  * @param {number} [options.visible_instance_hint] VG instances one expansion site is expected
26
28
  * to see; what {@link claim_word_capacity} is sized from, and nothing else
27
29
  * @param {number} [options.claim_word_capacity] words of the per-invocation claim bitmask,
28
30
  * overriding the derivation below
29
31
  * @param {number} [options.queue_capacity] traversal items one wavefront may hold
30
32
  * @param {number} [options.max_iterations] wavefronts before the descent is abandoned
31
- * @param {number} [options.cluster_chunk] clusters one group-chunk item covers
33
+ * @param {number} [options.descent_steps] steps of the descent one traversal dispatch runs
34
+ * before handing back what it still holds; see the traversal kernel for why it cannot
35
+ * simply stop when the wave runs dry
32
36
  */
33
- constructor({ pool, device, want_capacity, touch_capacity, visible_instance_hint, claim_word_capacity, queue_capacity, max_iterations, cluster_chunk, }: {
37
+ constructor({ pool, want_capacity, visible_instance_hint, claim_word_capacity, queue_capacity, max_iterations, descent_steps, }: {
34
38
  pool: GPUVirtualGeometryPool;
35
- device: GPUDevice;
36
39
  want_capacity?: number;
37
- touch_capacity?: number;
38
40
  visible_instance_hint?: number;
39
41
  claim_word_capacity?: number;
40
42
  queue_capacity?: number;
41
43
  max_iterations?: number;
42
- cluster_chunk?: number;
44
+ descent_steps?: number;
43
45
  });
44
46
  /**
45
47
  * Pixels of permitted error — the single quality/perf lever, and a runtime dial by design §4.
@@ -53,11 +55,13 @@ export class GPUVirtualGeometryRuntime {
53
55
  /**
54
56
  * @returns {GPUVirtualGeometryPool}
55
57
  */
56
- get pool(): GPUVirtualGeometryPool;
58
+ get pool(): import("./GPUVirtualGeometryPool.js").GPUVirtualGeometryPool;
57
59
  /**
58
- * @returns {GPUBuffer}
60
+ * Pages one frame may ask for, across every view.
61
+ *
62
+ * @returns {number}
59
63
  */
60
- get params_buffer(): GPUBuffer;
64
+ get want_capacity(): number;
61
65
  /**
62
66
  * @returns {number}
63
67
  */
@@ -70,6 +74,20 @@ export class GPUVirtualGeometryRuntime {
70
74
  * @returns {number}
71
75
  */
72
76
  get max_iterations(): number;
77
+ /**
78
+ * Settable, like tau, and for the same reason: it is a quality-of-schedule dial whose right
79
+ * value is a property of the asset's depth and the scene's breadth together rather than of the
80
+ * engine. `begin_frame` re-writes the params every frame, so a change lands on the next one.
81
+ *
82
+ * @param {number} value
83
+ */
84
+ set descent_steps(value: number);
85
+ /**
86
+ * Steps of the descent one traversal dispatch runs.
87
+ *
88
+ * @returns {number}
89
+ */
90
+ get descent_steps(): number;
73
91
  /**
74
92
  * This frame's feedback resource. Every expansion site writes into it and one readback reads it.
75
93
  * @returns {number}
@@ -95,31 +113,42 @@ export class GPUVirtualGeometryRuntime {
95
113
  * @returns {ReturnType<vgeo_cut_feedback_layout>}
96
114
  */
97
115
  get feedback_layout(): {
98
- touch_stamp_base: number;
99
- want_stamp_base: number;
116
+ touch_bits_base: number;
117
+ /**
118
+ * @type {number}
119
+ */
120
+ touch_word_count: number;
100
121
  want_base: number;
101
- touch_base: number;
102
- word_count: number;
122
+ word_count: number; /**
123
+ * @type {number}
124
+ */
103
125
  };
104
126
  /**
105
127
  * Open a frame: publish the page tables, size the feedback buffer against what is resident, and
106
128
  * write the parameters every pass of every view will read.
107
129
  *
108
- * The sizing happens here rather than at construction because two of its terms move with
109
- * residency — one touch stamp per page-table row, one want stamp per lookup word — and a frame
110
- * is the coarsest granularity at which they hold still.
130
+ * The sizing happens here rather than at construction because one of its terms moves with
131
+ * residency — one touch bit per page-table row — and a frame is the coarsest granularity at
132
+ * which it holds still.
111
133
  *
112
- * @param {FrameGraph} graph
113
- * @param {Object} view
114
- * @param {number} view.screen_height pixels of the render target
115
- * @param {number} view.fov_y radians
116
- * @param {number} [view.meshlet_capacity] records the shared meshlet collection holds
134
+ * **The pool's frame advances here, before the flush**, and not at `end_frame`. The frame
135
+ * number is what stamps a page row's `visible_from` — the frame whose flush publishes the
136
+ * row's occupant — and what a reading compares it against. With the advance here, an install
137
+ * landing anywhere after this frame's flush is stamped for the next one and rejected by this
138
+ * frame's reading, exactly (RUNTIME_PLAN_2026_09_14 §2.4). It is also the clock both tiers'
139
+ * protect windows read, and it moves whether or not a readback is scheduled this frame.
140
+ *
141
+ * **A frame has no projection.** It used to take one, and wrote it into a params buffer
142
+ * every view then shared — so a shadow cascade cut against whichever view opened the
143
+ * frame. `projection_k` is a property of a render target and a camera, which is to say of
144
+ * a view, and it lives on {@link VGeoViewCut} with the rest of what a view owns alone.
145
+ *
146
+ * @param {Object} options
147
+ * @param {FrameGraph} options.graph
117
148
  * @returns {number} the feedback resource
118
149
  */
119
- begin_frame(graph: FrameGraph, { screen_height, fov_y }: {
120
- screen_height: number;
121
- fov_y: number;
122
- meshlet_capacity?: number;
150
+ begin_frame({ graph }: {
151
+ graph: FrameGraph;
123
152
  }): number;
124
153
  /**
125
154
  * What one expansion site was handed, folded into the parameters every pass of the frame reads.
@@ -162,7 +191,7 @@ export class GPUVirtualGeometryRuntime {
162
191
  *
163
192
  * @returns {FrameGraph|undefined}
164
193
  */
165
- get frame_graph(): any;
194
+ get frame_graph(): import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
166
195
  /**
167
196
  * Close a frame. The feedback resource stops being valid; reading it is
168
197
  * {@link VGeoFeedbackLoop}'s, which schedules the readback while the graph is still being built.
@@ -170,7 +199,8 @@ export class GPUVirtualGeometryRuntime {
170
199
  * @returns {void}
171
200
  */
172
201
  end_frame(): void;
173
- destroy(): void;
174
202
  #private;
175
203
  }
204
+ export type GPUVirtualGeometryPool = import("./GPUVirtualGeometryPool.js").GPUVirtualGeometryPool;
205
+ export type FrameGraph = import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
176
206
  //# sourceMappingURL=GPUVirtualGeometryRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GPUVirtualGeometryRuntime.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;GAgBG;AACH;IAwFI;;;;;;;;;;;;;OAaG;IACH;QAZ2C,IAAI;QACjB,MAAM;QACR,aAAa,GAA9B,MAAM;QACW,cAAc,GAA/B,MAAM;QACW,qBAAqB,GAAtC,MAAM;QAEW,mBAAmB,GAApC,MAAM;QAEW,cAAc,GAA/B,MAAM;QACW,cAAc,GAA/B,MAAM;QACW,aAAa,GAA9B,MAAM;OAqDhB;IA3GD;;;OAGG;IACH,KAFU,MAAM,CAER;IAER;;OAEG;IACH,cAFU,OAAO,CAEG;IAoGpB;;OAEG;IACH,mCAEC;IAED;;OAEG;IACH,+BAEC;IAED;;OAEG;IACH,6BAEC;IAED;;OAEG;IACH,kCAEC;IAED;;OAEG;IACH,6BAEC;IAED;;;OAGG;IACH,uBAEC;IAED;;;;;;;;;;;;;;OAcG;IACH,yBAHW,MAAM,GACJ,IAAI,CAMhB;IAED;;OAEG;IACH;;;;;;MAEC;IAED;;;;;;;;;;;;;;OAcG;IACH;QALwB,aAAa,EAA1B,MAAM;QACO,KAAK,EAAlB,MAAM;QACQ,gBAAgB,GAA9B,MAAM;QACJ,MAAM,CAqClB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH;QAJ2B,iBAAiB,EAAjC,MAAM;QACU,gBAAgB,EAAhC,MAAM;QACJ,IAAI,CAehB;IAED;;OAEG;IACH,gCAEC;IAED;;OAEG;IACH,+BAEC;IAED;;;;;;;;;;OAUG;IACH,uBAEC;IAyBD;;;;;OAKG;IACH,aAFa,IAAI,CAOhB;IAED,gBAEC;;CACJ"}
1
+ {"version":3,"file":"GPUVirtualGeometryRuntime.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js"],"names":[],"mappings":"AAKA;;;GAGG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH;IAwEI;;;;;;;;;;;;;OAaG;IACH;QAZ2C,IAAI,EAApC,sBAAsB;QACL,aAAa,GAA9B,MAAM;QACW,qBAAqB,GAAtC,MAAM;QAEW,mBAAmB,GAApC,MAAM;QAEW,cAAc,GAA/B,MAAM;QACW,cAAc,GAA/B,MAAM;QACW,aAAa,GAA9B,MAAM;OA+DhB;IA/GD;;;OAGG;IACH,KAFU,MAAM,CAER;IAER;;OAEG;IACH,cAFU,OAAO,CAEG;IAwGpB;;OAEG;IACH,yEAEC;IAED;;;;OAIG;IACH,4BAEC;IAED;;OAEG;IACH,6BAEC;IAED;;OAEG;IACH,kCAEC;IAED;;OAEG;IACH,6BAEC;IAWD;;;;;;OAMG;IACH,iCAKC;IArBD;;;;OAIG;IACH,4BAEC;IAgBD;;;OAGG;IACH,uBAEC;IAED;;;;;;;;;;;;;;OAcG;IACH,yBAHW,MAAM,GACJ,IAAI,CAMhB;IAED;;OAEG;IACH;;QAvOA;;WAEG;;;4BAIH;;WAEG;MAiOF;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH;QAH+B,KAAK,EAAzB,UAAU;QACR,MAAM,CA+BlB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH;QAJ2B,iBAAiB,EAAjC,MAAM;QACU,gBAAgB,EAAhC,MAAM;QACJ,IAAI,CAahB;IAED;;OAEG;IACH,gCAEC;IAED;;OAEG;IACH,+BAEC;IAED;;;;;;;;;;OAUG;IACH,wGAEC;IAGD;;;;;OAKG;IACH,aAFa,IAAI,CAKhB;;CACJ;qCAtYY,OAAO,6BAA6B,EAAE,sBAAsB;yBAC5D,OAAO,iEAAiE,EAAE,UAAU"}
@@ -1,11 +1,13 @@
1
1
  import { assert } from "../../../../../core/assert.js";
2
2
  import { BufferResourceDescriptor } from "../../../../device/graph/BufferResourceDescriptor.js";
3
3
  import { noop } from "../../../../../core/function/noop.js";
4
- import { write_gpu_typed_buffer } from "../../../shader/type/serde/write_gpu_typed_buffer.js";
5
- import { VGEO_CUT_FLAG_CULL } from "./cut/VGEO_CUT_FLAG_CULL.js";
6
- import { VGEO_CUT_PARAMS_STRUCT } from "./cut/VGEO_CUT_PARAMS_STRUCT.js";
7
4
  import { vgeo_cut_feedback_layout } from "./cut/vgeo_cut_feedback_layout.js";
8
5
 
6
+ /**
7
+ * @typedef {import("./GPUVirtualGeometryPool.js").GPUVirtualGeometryPool} GPUVirtualGeometryPool
8
+ * @typedef {import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
9
+ */
10
+
9
11
  /**
10
12
  * What one frame of virtual geometry needs that is not a page: the threshold, the feedback buffer
11
13
  * every view writes into, and the parameters every pass reads.
@@ -29,25 +31,13 @@ export class GPUVirtualGeometryRuntime {
29
31
  */
30
32
  #pool;
31
33
 
32
- /**
33
- * @type {GPUDevice}
34
- */
35
- #device;
36
34
 
37
- /**
38
- * @type {GPUBuffer}
39
- */
40
- #params;
41
35
 
42
36
  /**
43
37
  * @type {number}
44
38
  */
45
39
  #want_capacity;
46
40
 
47
- /**
48
- * @type {number}
49
- */
50
- #touch_capacity;
51
41
 
52
42
  /**
53
43
  * @type {number}
@@ -67,7 +57,7 @@ export class GPUVirtualGeometryRuntime {
67
57
  /**
68
58
  * @type {number}
69
59
  */
70
- #cluster_chunk;
60
+ #descent_steps;
71
61
 
72
62
  /**
73
63
  * Pixels of permitted error — the single quality/perf lever, and a runtime dial by design §4.
@@ -96,10 +86,6 @@ export class GPUVirtualGeometryRuntime {
96
86
  */
97
87
  #graph;
98
88
 
99
- /**
100
- * @type {number}
101
- */
102
- #projection_k = 1;
103
89
 
104
90
  /**
105
91
  * @type {number}
@@ -114,22 +100,20 @@ export class GPUVirtualGeometryRuntime {
114
100
  /**
115
101
  * @param {Object} options
116
102
  * @param {GPUVirtualGeometryPool} options.pool
117
- * @param {GPUDevice} options.device
118
103
  * @param {number} [options.want_capacity] pages one frame may ask for, across every view
119
- * @param {number} [options.touch_capacity] page rows one frame may report drawing from
120
104
  * @param {number} [options.visible_instance_hint] VG instances one expansion site is expected
121
105
  * to see; what {@link claim_word_capacity} is sized from, and nothing else
122
106
  * @param {number} [options.claim_word_capacity] words of the per-invocation claim bitmask,
123
107
  * overriding the derivation below
124
108
  * @param {number} [options.queue_capacity] traversal items one wavefront may hold
125
109
  * @param {number} [options.max_iterations] wavefronts before the descent is abandoned
126
- * @param {number} [options.cluster_chunk] clusters one group-chunk item covers
110
+ * @param {number} [options.descent_steps] steps of the descent one traversal dispatch runs
111
+ * before handing back what it still holds; see the traversal kernel for why it cannot
112
+ * simply stop when the wave runs dry
127
113
  */
128
114
  constructor({
129
115
  pool,
130
- device,
131
116
  want_capacity = 2048,
132
- touch_capacity = 8192,
133
117
  visible_instance_hint = 1024,
134
118
  /*
135
119
  One bit per (instance, page ordinal), and the two terms are the *pool's* page
@@ -156,26 +140,36 @@ export class GPUVirtualGeometryRuntime {
156
140
  with work outstanding, which is the one degradation that costs a hole.
157
141
  */
158
142
  queue_capacity = 1 << 16,
159
- max_iterations = 64,
160
- cluster_chunk = 8,
143
+ max_iterations = 8,
144
+ /*
145
+ Steps of the in-kernel descent one dispatch runs, and the knob that is *not*
146
+ the safety bound — `max_iterations` is, and lowering this spends it. A wave
147
+ keeps one child per lane and spills the rest, so a dispatch advances what it
148
+ held by `descent_steps` levels and hands the rest to the next one: the
149
+ dispatches a cut needs are `ceil(depth / descent_steps)` plus its spill
150
+ generations, not `depth / descent_steps`. Running out of dispatches is
151
+ `VGEO_CUT_STAT.QUEUE_REMAINING`, and that is a hole rather than coarseness.
152
+
153
+ Measured over a full orbit of the deepest converted Zorah container — 27.9M
154
+ faces, 17,172 pages, 39 levels — at tau 1, the dispatches it needs are 6 at 32
155
+ and at 24, 7 at 20, all 8 at 16 and at 12, and more than 8 below that. So 24 is
156
+ the most this can be lowered for nothing: the same six dispatches 32 needs,
157
+ with a quarter fewer idle steps inside each. `DRAWN` is bit-identical at every
158
+ value that drains, which is what makes this a schedule knob and not a quality
159
+ one.
160
+ */
161
+ descent_steps = 24,
161
162
  }) {
162
163
  assert.defined(pool, 'pool');
163
- assert.defined(device, 'device');
164
164
 
165
165
  this.#pool = pool;
166
- this.#device = device;
167
166
  this.#want_capacity = want_capacity;
168
- this.#touch_capacity = touch_capacity;
169
167
  this.#claim_word_capacity = claim_word_capacity;
170
168
  this.#queue_capacity = queue_capacity;
171
169
  this.#max_iterations = max_iterations;
172
- this.#cluster_chunk = cluster_chunk;
170
+ this.#descent_steps = descent_steps;
171
+
173
172
 
174
- this.#params = device.createBuffer({
175
- label: 'GPUVirtualGeometryRuntime/params',
176
- size: VGEO_CUT_PARAMS_STRUCT.aligned_size,
177
- usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
178
- });
179
173
  }
180
174
 
181
175
  /**
@@ -186,10 +180,12 @@ export class GPUVirtualGeometryRuntime {
186
180
  }
187
181
 
188
182
  /**
189
- * @returns {GPUBuffer}
183
+ * Pages one frame may ask for, across every view.
184
+ *
185
+ * @returns {number}
190
186
  */
191
- get params_buffer() {
192
- return this.#params;
187
+ get want_capacity() {
188
+ return this.#want_capacity;
193
189
  }
194
190
 
195
191
  /**
@@ -213,6 +209,29 @@ export class GPUVirtualGeometryRuntime {
213
209
  return this.#max_iterations;
214
210
  }
215
211
 
212
+ /**
213
+ * Steps of the descent one traversal dispatch runs.
214
+ *
215
+ * @returns {number}
216
+ */
217
+ get descent_steps() {
218
+ return this.#descent_steps;
219
+ }
220
+
221
+ /**
222
+ * Settable, like tau, and for the same reason: it is a quality-of-schedule dial whose right
223
+ * value is a property of the asset's depth and the scene's breadth together rather than of the
224
+ * engine. `begin_frame` re-writes the params every frame, so a change lands on the next one.
225
+ *
226
+ * @param {number} value
227
+ */
228
+ set descent_steps(value) {
229
+ assert.isNonNegativeInteger(value, 'descent_steps');
230
+ assert.greaterThan(value, 0, 'descent_steps');
231
+
232
+ this.#descent_steps = value;
233
+ }
234
+
216
235
  /**
217
236
  * This frame's feedback resource. Every expansion site writes into it and one readback reads it.
218
237
  * @returns {number}
@@ -253,28 +272,35 @@ export class GPUVirtualGeometryRuntime {
253
272
  * Open a frame: publish the page tables, size the feedback buffer against what is resident, and
254
273
  * write the parameters every pass of every view will read.
255
274
  *
256
- * The sizing happens here rather than at construction because two of its terms move with
257
- * residency — one touch stamp per page-table row, one want stamp per lookup word — and a frame
258
- * is the coarsest granularity at which they hold still.
275
+ * The sizing happens here rather than at construction because one of its terms moves with
276
+ * residency — one touch bit per page-table row — and a frame is the coarsest granularity at
277
+ * which it holds still.
278
+ *
279
+ * **The pool's frame advances here, before the flush**, and not at `end_frame`. The frame
280
+ * number is what stamps a page row's `visible_from` — the frame whose flush publishes the
281
+ * row's occupant — and what a reading compares it against. With the advance here, an install
282
+ * landing anywhere after this frame's flush is stamped for the next one and rejected by this
283
+ * frame's reading, exactly (RUNTIME_PLAN_2026_09_14 §2.4). It is also the clock both tiers'
284
+ * protect windows read, and it moves whether or not a readback is scheduled this frame.
285
+ *
286
+ * **A frame has no projection.** It used to take one, and wrote it into a params buffer
287
+ * every view then shared — so a shadow cascade cut against whichever view opened the
288
+ * frame. `projection_k` is a property of a render target and a camera, which is to say of
289
+ * a view, and it lives on {@link VGeoViewCut} with the rest of what a view owns alone.
259
290
  *
260
- * @param {FrameGraph} graph
261
- * @param {Object} view
262
- * @param {number} view.screen_height pixels of the render target
263
- * @param {number} view.fov_y radians
264
- * @param {number} [view.meshlet_capacity] records the shared meshlet collection holds
291
+ * @param {Object} options
292
+ * @param {FrameGraph} options.graph
265
293
  * @returns {number} the feedback resource
266
294
  */
267
- begin_frame(graph, { screen_height, fov_y }) {
295
+ begin_frame({ graph }) {
268
296
  assert.defined(graph, 'graph');
269
- assert.greaterThan(screen_height, 0, 'screen_height');
270
297
 
298
+ this.#pool.advance_frame();
271
299
  this.#pool.flush();
272
300
 
273
301
  this.#layout = vgeo_cut_feedback_layout({
274
302
  page_row_capacity: this.#pool.page_row_capacity,
275
- lookup_word_count: this.#pool.lookup_word_count,
276
303
  want_capacity: this.#want_capacity,
277
- touch_capacity: this.#touch_capacity,
278
304
  });
279
305
 
280
306
  const spawn = graph.add('vgeo/frame', {}, noop);
@@ -294,10 +320,6 @@ export class GPUVirtualGeometryRuntime {
294
320
  this.#instance_capacity = 0;
295
321
  this.#meshlet_capacity = 0;
296
322
 
297
- this.#projection_k = screen_height / (2 * Math.tan(fov_y * 0.5));
298
-
299
- this.#write_params();
300
-
301
323
  return this.#feedback;
302
324
  }
303
325
 
@@ -330,8 +352,6 @@ export class GPUVirtualGeometryRuntime {
330
352
  this.#meshlet_capacity = this.#meshlet_capacity === 0
331
353
  ? meshlet_capacity
332
354
  : Math.min(this.#meshlet_capacity, meshlet_capacity);
333
-
334
- this.#write_params();
335
355
  }
336
356
 
337
357
  /**
@@ -363,28 +383,6 @@ export class GPUVirtualGeometryRuntime {
363
383
  return this.#graph;
364
384
  }
365
385
 
366
- /**
367
- * @returns {void}
368
- */
369
- #write_params() {
370
- write_gpu_typed_buffer_to_device(this.#device, this.#params, {
371
- tau: this.tau,
372
- projection_k: this.#projection_k,
373
- queue_capacity: this.#queue_capacity,
374
- claim_word_count: this.#claim_word_capacity,
375
- cluster_chunk: this.#cluster_chunk,
376
- page_slot_words: this.#pool.page_slot_words,
377
- touch_stamp_base: this.#layout.touch_stamp_base,
378
- want_stamp_base: this.#layout.want_stamp_base,
379
- want_base: this.#layout.want_base,
380
- want_capacity: this.#want_capacity,
381
- touch_base: this.#layout.touch_base,
382
- touch_capacity: this.#touch_capacity,
383
- instance_capacity: this.#instance_capacity,
384
- meshlet_capacity: this.#meshlet_capacity,
385
- flags: this.cull_enabled ? VGEO_CUT_FLAG_CULL : 0,
386
- });
387
- }
388
386
 
389
387
  /**
390
388
  * Close a frame. The feedback resource stops being valid; reading it is
@@ -395,31 +393,5 @@ export class GPUVirtualGeometryRuntime {
395
393
  end_frame() {
396
394
  this.#feedback = -1;
397
395
  this.#graph = undefined;
398
-
399
- this.#pool.advance_frame();
400
396
  }
401
-
402
- destroy() {
403
- this.#params.destroy();
404
- }
405
- }
406
-
407
- /**
408
- * `write_gpu_typed_buffer` writes into an `ArrayBuffer`; a uniform wants bytes on a device. One
409
- * scratch buffer rather than one per frame, because the params block is forty-odd bytes written
410
- * once a frame and allocating for it would be the expensive half.
411
- *
412
- * @type {ArrayBuffer}
413
- */
414
- const PARAMS_SCRATCH = new ArrayBuffer(VGEO_CUT_PARAMS_STRUCT.aligned_size);
415
-
416
- /**
417
- * @param {GPUDevice} device
418
- * @param {GPUBuffer} buffer
419
- * @param {Object} value
420
- */
421
- function write_gpu_typed_buffer_to_device(device, buffer, value) {
422
- write_gpu_typed_buffer(value, VGEO_CUT_PARAMS_STRUCT, PARAMS_SCRATCH, 0);
423
-
424
- device.queue.writeBuffer(buffer, 0, PARAMS_SCRATCH, 0, VGEO_CUT_PARAMS_STRUCT.aligned_size);
425
397
  }
@@ -239,3 +239,40 @@ Two things this pass could not prove below the drive, written down rather than c
239
239
  implemented as a per-reader one.** `VGeoResidencyManager`'s own doc records the first being
240
240
  measured at 48 concurrent range requests against a cap of six, and that is why its gate is shared.
241
241
  Worth a grep the next time a limit is added: the reader-shaped one is the easy one to write.
242
+
243
+ ## 2026-09-14 — the remainder counter never worked
244
+
245
+ `QUEUE_REMAINING` read zero at every iteration budget, including the ones where the descent drew
246
+ nothing at all. M8 added the counter and a spec for it, and both were right about a frame with one
247
+ cut in it; the engine has never recorded a frame with one cut in it.
248
+
249
+ Measured on `zorah-2026-13-09/bdf6f9615ae672d54bfb70cde904f5c2.vgeo` (28M faces, 17,172 pages)
250
+ through the playground on a 4090, sweeping `max_iterations` at tau = 1:
251
+
252
+ | `max_iterations` | pages | drawn | remaining, before | after |
253
+ | --- | --- | --- | --- | --- |
254
+ | 40 | 1593 | 10177 | 0 | 0 |
255
+ | 39 | 1593 | 10177 | 0 | 0 |
256
+ | 38 | 1593 | 10170 | 0 | 7 |
257
+ | 32 | 1315 | 2115 | 0 | 4556 |
258
+ | 20 | 25 | 0 | 0 | 75 |
259
+
260
+ Two causes, and they cancelled into a plausible number:
261
+
262
+ - **The prepare pass wrote it, and the prepare pass runs between wavefronts.** What it could report
263
+ is the frontier of an iteration, not a remainder, and the next iteration overwrote it. Only a pass
264
+ after the last wavefront is looking at the right thing.
265
+ - **It was a plain store, and a frame has more than one cut.** The two-way HZB filter gives every
266
+ view two expansion sites and a scene routinely has all of its virtual geometry in one of them, so
267
+ the *empty* bucket ran last and stored its own zero over the other's truncation. Every other stat
268
+ in `VGEO_CUT_STAT` is an add across the frame's cuts; this one was not.
269
+
270
+ `shader_vgeo_cut_queue_remainder` is the tail now — three bindings, one workgroup, an `atomicAdd` —
271
+ and the prepare pass no longer binds the feedback buffer at all. The spec that missed it ran one
272
+ cut against one feedback buffer, which is the only arrangement in which a last-writer-wins race has
273
+ no second writer; the new one runs a truncated cut and an empty cut against the buffer
274
+ `begin_frame` would have given them both.
275
+
276
+ **What this unblocks.** `max_iterations` defaults to 64 and the descent on this asset converges at
277
+ 39, so 89 of the 128 traverse dispatches a frame records are empty — and until now nothing could
278
+ say whether a smaller budget was safe. It can now: 39 is exact and 40 is free.