@woosh/meep-engine 3.64.1 → 3.65.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 (324) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/build/bundle-worker-image-decoder.js +1 -1
  3. package/build/bundle-worker-terrain.js +1 -1
  4. package/package.json +1 -1
  5. package/src/core/binary/BinaryBuffer.d.ts +5 -0
  6. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  7. package/src/core/binary/BinaryBuffer.js +39 -5
  8. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts +65 -6
  9. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts.map +1 -1
  10. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +451 -101
  11. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +4 -2
  12. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -1
  13. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +4 -2
  14. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts +8 -1
  15. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts.map +1 -1
  16. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +45 -10
  17. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
  18. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +237 -119
  19. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts +143 -0
  20. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts.map +1 -0
  21. package/src/engine/graphics/ecs/grass/GrassSpecies.js +189 -0
  22. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts +25 -0
  23. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts.map +1 -0
  24. package/src/engine/graphics/ecs/grass/GrassSurface.js +32 -0
  25. package/src/engine/graphics/ecs/grass/GroundCover.d.ts +68 -0
  26. package/src/engine/graphics/ecs/grass/GroundCover.d.ts.map +1 -0
  27. package/src/engine/graphics/ecs/grass/GroundCover.js +85 -0
  28. package/src/engine/graphics3/GrassSurfaceSystem.d.ts +153 -0
  29. package/src/engine/graphics3/GrassSurfaceSystem.d.ts.map +1 -0
  30. package/src/engine/graphics3/GrassSurfaceSystem.js +1076 -0
  31. package/src/engine/graphics3/GroundCoverSystem.d.ts +33 -0
  32. package/src/engine/graphics3/GroundCoverSystem.d.ts.map +1 -0
  33. package/src/engine/graphics3/GroundCoverSystem.js +58 -0
  34. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  35. package/src/engine/network/NetworkSession.js +372 -110
  36. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  37. package/src/engine/network/orchestrator/NetworkPeer.js +6 -1
  38. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  39. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +9 -2
  40. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  41. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +325 -140
  42. package/src/engine/network/sim/SimActionExecutor.d.ts +4 -1
  43. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  44. package/src/engine/network/sim/SimActionExecutor.js +65 -9
  45. package/src/engine/network/state/PredictionHistory.d.ts.map +1 -1
  46. package/src/engine/network/state/PredictionHistory.js +6 -1
  47. package/src/engine/network/time/AdaptiveRenderDelay.d.ts +25 -14
  48. package/src/engine/network/time/AdaptiveRenderDelay.d.ts.map +1 -1
  49. package/src/engine/network/time/AdaptiveRenderDelay.js +38 -20
  50. package/src/engine/network/time/RenderPlayout.d.ts +23 -3
  51. package/src/engine/network/time/RenderPlayout.d.ts.map +1 -1
  52. package/src/engine/network/time/RenderPlayout.js +40 -4
  53. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  54. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts +5 -1
  55. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts.map +1 -1
  56. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.js +27 -1
  57. package/src/shade/device/shader/ShaderModuleCompiler.d.ts +2 -0
  58. package/src/shade/device/shader/ShaderModuleCompiler.d.ts.map +1 -1
  59. package/src/shade/device/shader/ShaderModuleCompiler.js +25 -2
  60. package/src/shade/playground/grass_surfaces/index.html +75 -0
  61. package/src/shade/playground/grass_surfaces/main.d.ts +2 -0
  62. package/src/shade/playground/grass_surfaces/main.d.ts.map +1 -0
  63. package/src/shade/playground/grass_surfaces/main.js +593 -0
  64. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts +62 -0
  65. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts.map +1 -0
  66. package/src/shade/playground/grass_surfaces/read_grass_surfaces.js +188 -0
  67. package/src/shade/playground/probe_clipmap_box/README.md +5 -1
  68. package/src/shade/playground/probe_clipmap_box/index.html +12 -0
  69. package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -1
  70. package/src/shade/playground/probe_clipmap_box/main.js +15 -0
  71. package/src/shade/playground/probe_clipmap_box/scene.d.ts +8 -1
  72. package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -1
  73. package/src/shade/playground/probe_clipmap_box/scene.js +74 -6
  74. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  75. package/src/shade/renderer/Renderer.js +47 -43
  76. package/src/shade/renderer/extension/ViewTextures.d.ts +12 -5
  77. package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
  78. package/src/shade/renderer/extension/ViewTextures.js +19 -5
  79. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +3 -1
  80. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
  81. package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +6 -1
  82. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +7 -0
  83. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts.map +1 -1
  84. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.js +10 -0
  85. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +7 -1
  86. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  87. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +46 -15
  88. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts +3 -2
  89. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts.map +1 -1
  90. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.js +3 -2
  91. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts +22 -0
  92. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts.map +1 -0
  93. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.js +247 -0
  94. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +50 -0
  95. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  96. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +101 -0
  97. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +2 -1
  98. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  99. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +2 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +8 -0
  101. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  102. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +12 -0
  103. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +12 -6
  104. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +35 -29
  106. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.d.ts.map +1 -1
  107. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.js +4 -2
  108. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.js +6 -4
  110. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.d.ts.map +1 -1
  111. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.js +2 -1
  112. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts +6 -5
  113. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts.map +1 -1
  114. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.js +15 -14
  115. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.d.ts.map +1 -1
  116. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.js +4 -2
  117. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +19 -2
  118. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  119. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +128 -10
  120. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +19 -1
  121. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  122. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +27 -2
  123. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts +19 -11
  124. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts.map +1 -1
  125. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.js +35 -11
  126. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +3 -1
  128. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts +40 -0
  129. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts.map +1 -0
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.js +174 -0
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.d.ts +4 -4
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.js +10 -10
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts +31 -0
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts.map +1 -0
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.js +54 -0
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +8 -4
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +10 -21
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts +7 -2
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts.map +1 -1
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js +33 -29
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts +28 -0
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts.map +1 -0
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.js +138 -0
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +13 -9
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +18 -11
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +1 -1
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.d.ts.map +1 -1
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +4 -2
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +2 -3
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +5 -3
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +15 -30
  156. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -1
  157. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  158. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +4 -2
  159. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts +11 -0
  160. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts.map +1 -1
  161. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +29 -2
  162. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts +40 -0
  163. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts.map +1 -0
  164. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.js +126 -0
  165. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts +36 -0
  166. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts.map +1 -0
  167. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.js +221 -0
  168. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts +40 -0
  169. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts.map +1 -0
  170. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.js +86 -0
  171. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts +135 -0
  172. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts.map +1 -0
  173. package/src/shade/renderer/grass/blade/GPUGrassBlades.js +676 -0
  174. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts +145 -0
  175. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts.map +1 -0
  176. package/src/shade/renderer/grass/blade/GRASS_BLADE.js +179 -0
  177. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts +63 -0
  178. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts.map +1 -0
  179. package/src/shade/renderer/grass/blade/chunk_grass_blade.js +244 -0
  180. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts +58 -0
  181. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts.map +1 -0
  182. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.js +174 -0
  183. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts +25 -0
  184. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts.map +1 -0
  185. package/src/shade/renderer/grass/blade/grass_blade_id_draw.js +133 -0
  186. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts +80 -0
  187. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts.map +1 -0
  188. package/src/shade/renderer/grass/blade/grass_blade_mechanics.js +92 -0
  189. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts +29 -0
  190. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts.map +1 -0
  191. package/src/shade/renderer/grass/blade/grass_blade_resolve.js +175 -0
  192. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts +14 -0
  193. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts.map +1 -0
  194. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.js +45 -0
  195. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts +61 -0
  196. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts.map +1 -0
  197. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.js +340 -0
  198. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts +46 -0
  199. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts.map +1 -0
  200. package/src/shade/renderer/grass/blade/shader_grass_cell_count.js +280 -0
  201. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts +60 -0
  202. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts.map +1 -0
  203. package/src/shade/renderer/grass/population/chunk_grass_population.js +171 -0
  204. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts +99 -0
  205. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts.map +1 -0
  206. package/src/shade/renderer/grass/press/GPUGrassPress.js +436 -0
  207. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts +179 -0
  208. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts.map +1 -0
  209. package/src/shade/renderer/grass/press/GRASS_PRESS.js +217 -0
  210. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts +65 -0
  211. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts.map +1 -0
  212. package/src/shade/renderer/grass/press/chunk_grass_press.js +296 -0
  213. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts +31 -0
  214. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts.map +1 -0
  215. package/src/shade/renderer/grass/press/shader_grass_press_mark.js +169 -0
  216. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts +27 -0
  217. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts.map +1 -0
  218. package/src/shade/renderer/grass/press/shader_grass_press_stamp.js +183 -0
  219. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts +193 -0
  220. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts.map +1 -0
  221. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.js +1253 -0
  222. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts +211 -0
  223. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts.map +1 -0
  224. package/src/shade/renderer/grass/surface/GRASS_SURFACE.js +241 -0
  225. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts +82 -0
  226. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts.map +1 -0
  227. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.js +111 -0
  228. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts +39 -0
  229. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts.map +1 -0
  230. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.js +85 -0
  231. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts +29 -0
  232. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts.map +1 -0
  233. package/src/shade/renderer/grass/surface/chunk_grass_directory.js +112 -0
  234. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts +27 -0
  235. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts.map +1 -0
  236. package/src/shade/renderer/grass/surface/chunk_grass_slot.js +50 -0
  237. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts +21 -0
  238. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts.map +1 -0
  239. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.js +41 -0
  240. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts +32 -0
  241. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts.map +1 -0
  242. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.js +136 -0
  243. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts +37 -0
  244. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts.map +1 -0
  245. package/src/shade/renderer/grass/surface/chunk_grass_surfel.js +85 -0
  246. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts +25 -0
  247. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts.map +1 -0
  248. package/src/shade/renderer/grass/surface/chunk_grass_tile.js +52 -0
  249. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts +23 -0
  250. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts.map +1 -0
  251. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.js +87 -0
  252. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts +43 -0
  253. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts.map +1 -0
  254. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.js +265 -0
  255. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts +13 -0
  256. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts.map +1 -0
  257. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.js +49 -0
  258. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts +62 -0
  259. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts.map +1 -0
  260. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.js +162 -0
  261. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts +40 -0
  262. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts.map +1 -0
  263. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.js +155 -0
  264. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts +19 -0
  265. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts.map +1 -0
  266. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.js +58 -0
  267. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts +30 -0
  268. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts.map +1 -0
  269. package/src/shade/renderer/grass/surface/shader_grass_surface_want.js +251 -0
  270. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts +21 -0
  271. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts.map +1 -0
  272. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.js +75 -0
  273. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
  274. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +4 -23
  275. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts +12 -0
  276. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts.map +1 -0
  277. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.js +29 -0
  278. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  279. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +22 -0
  280. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  281. package/src/shade/renderer/scene/GPUSceneContext.js +3 -0
  282. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts +27 -0
  283. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts.map +1 -0
  284. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.js +38 -0
  285. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts +28 -0
  286. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts.map +1 -0
  287. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.js +58 -0
  288. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
  289. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +8 -0
  290. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts +37 -0
  291. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts.map +1 -0
  292. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.js +148 -0
  293. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts +20 -0
  294. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts.map +1 -0
  295. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.js +169 -0
  296. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts +18 -0
  297. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts.map +1 -1
  298. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.js +28 -0
  299. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts +13 -0
  300. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts.map +1 -0
  301. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.js +22 -0
  302. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  303. package/src/shade/renderer/water/GPUWaterRenderer.js +4 -0
  304. package/src/shade/renderer/wind/GPUSceneWind.d.ts +52 -5
  305. package/src/shade/renderer/wind/GPUSceneWind.d.ts.map +1 -1
  306. package/src/shade/renderer/wind/GPUSceneWind.js +164 -8
  307. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts +3 -1
  308. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts.map +1 -1
  309. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.js +3 -1
  310. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts +2 -1
  311. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts.map +1 -1
  312. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.js +18 -13
  313. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts +13 -0
  314. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts.map +1 -0
  315. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.js +23 -0
  316. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts +1 -0
  317. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts.map +1 -1
  318. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.js +6 -1
  319. package/src/shade/renderer/wind/wind_field_add_resources.d.ts +11 -0
  320. package/src/shade/renderer/wind/wind_field_add_resources.d.ts.map +1 -1
  321. package/src/shade/renderer/wind/wind_field_add_resources.js +15 -0
  322. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
  323. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  324. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
@@ -2,6 +2,11 @@
2
2
  * @type {WebGPUStruct}
3
3
  */
4
4
  export const PROBE_WANT_SETTINGS: WebGPUStruct;
5
+ /**
6
+ * {@link PROBE_WANT_SETTINGS} and how the surface's normals are read.
7
+ * @type {WebGPUStruct}
8
+ */
9
+ export const PROBE_WANT_SURFACE_SETTINGS: WebGPUStruct;
5
10
  /**
6
11
  * Want (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): a thread a tile of {@link PROBE_WANT_TILE}² pixels,
7
12
  * the launch the screen's tiles.
@@ -10,6 +15,12 @@ export const PROBE_WANT_SETTINGS: WebGPUStruct;
10
15
  * that pixel's pick reads (§9.1), biased along `mix(n, v, 0.2)`, through `probe_clipmap_want`. A sky
11
16
  * pixel wants nothing.
12
17
  *
18
+ * The surface is any the frame holds a depth and a normal of, a pixel each: the G-buffer's, or one drawn
19
+ * apart from it whose reader picks its probes per pixel, the water's interface. `gBufferDepth` is its
20
+ * reverse-Z depth, zero where it has no surface; `gBufferNormals` its normals, octahedral in the channel
21
+ * `settings.normal_channel`, as the G-buffer packs its own in its first. Where `settings.two_sided` is set,
22
+ * a normal that faces away from the eye is turned to face it, as a reader of such a surface turns it.
23
+ *
13
24
  * At a cascade's outer edge a lattice cell is 58 pixels on a 1080p screen at a 60° field of view, and
14
25
  * 19 at 120°, so a tile of 8 samples every cell several times a frame, and a workgroup's 64 tiles want
15
26
  * a few cages between them, which its claims keep to one want each.
@@ -1 +1 @@
1
- {"version":3,"file":"shader_probe_clipmap_want.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js"],"names":[],"mappings":"AAqBA;;GAEG;AACH,kCAFU,YAAY,CAcE;AAexB;;;;;;;;;;;;;GAaG;AACH,wCAFU,aAAa,CAqCpB;6BA1F0B,sCAAsC;8BAHrC,kCAAkC"}
1
+ {"version":3,"file":"shader_probe_clipmap_want.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js"],"names":[],"mappings":"AAqBA;;GAEG;AACH,kCAFU,YAAY,CAcE;AAExB;;;GAGG;AACH,0CAFU,YAAY,CAaS;AAe/B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wCAFU,aAAa,CAyCpB;6BArH0B,sCAAsC;8BAHrC,kCAAkC"}
@@ -36,9 +36,26 @@ export const PROBE_WANT_SETTINGS = WebGPUStruct.from({
36
36
  select_half: f32,
37
37
  }, "ProbeWantSettings");
38
38
 
39
+ /**
40
+ * {@link PROBE_WANT_SETTINGS} and how the surface's normals are read.
41
+ * @type {WebGPUStruct}
42
+ */
43
+ export const PROBE_WANT_SURFACE_SETTINGS = WebGPUStruct.from({
44
+ cascade_count: u32,
45
+ resolution: u32,
46
+ frame: u32,
47
+ wanted_capacity: u32,
48
+ anchor: vec3f,
49
+ select_half: f32,
50
+ /** the channel of the normals' texel that holds the normal: 0 to 3 */
51
+ normal_channel: u32,
52
+ /** non-zero where a normal may face away from the eye and its reader turns it to face it */
53
+ two_sided: u32,
54
+ }, "ProbeWantSurfaceSettings");
55
+
39
56
  const resources = new ShaderResourceSetDescriptor();
40
57
 
41
- resources.setImmediate("settings", PROBE_WANT_SETTINGS);
58
+ resources.setImmediate("settings", PROBE_WANT_SURFACE_SETTINGS);
42
59
 
43
60
  resources.createGroup()
44
61
  .addTexture("gBufferDepth")
@@ -57,6 +74,12 @@ resources.createGroup()
57
74
  * that pixel's pick reads (§9.1), biased along `mix(n, v, 0.2)`, through `probe_clipmap_want`. A sky
58
75
  * pixel wants nothing.
59
76
  *
77
+ * The surface is any the frame holds a depth and a normal of, a pixel each: the G-buffer's, or one drawn
78
+ * apart from it whose reader picks its probes per pixel, the water's interface. `gBufferDepth` is its
79
+ * reverse-Z depth, zero where it has no surface; `gBufferNormals` its normals, octahedral in the channel
80
+ * `settings.normal_channel`, as the G-buffer packs its own in its first. Where `settings.two_sided` is set,
81
+ * a normal that faces away from the eye is turned to face it, as a reader of such a surface turns it.
82
+ *
60
83
  * At a cascade's outer edge a lattice cell is 58 pixels on a 1080p screen at a 60° field of view, and
61
84
  * 19 at 120°, so a tile of 8 samples every cell several times a frame, and a workgroup's 64 tiles want
62
85
  * a few cages between them, which its claims keep to one want each.
@@ -83,8 +106,12 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
83
106
 
84
107
  let uv = (vec2<f32>(pixel) + 0.5) / vec2<f32>(size);
85
108
  let position = project_position_from_depth(uv, depth, camera.view_projection_matrix_inverse);
86
- let normal = decode_g_buffer_normal(textureLoad(gBufferNormals, pixel, 0).x);
109
+ let texel = textureLoad(gBufferNormals, pixel, 0);
110
+ // each channel by name: a dynamic index would put the texel in local memory
111
+ let encoded = select(select(texel.x, texel.y, settings.normal_channel == 1u), select(texel.z, texel.w, settings.normal_channel == 3u), settings.normal_channel >= 2u);
112
+ let stored = decode_g_buffer_normal(encoded);
87
113
  let view_direction = normalize(mat4_extract_position(camera.transform) - position);
114
+ let normal = select(stored, -stored, settings.two_sided != 0u && dot(stored, view_direction) < 0.0);
88
115
  let bias_direction = mix(normal, view_direction, ${PROBE_RECEIVER_BIAS_VIEW});
89
116
 
90
117
  probe_clipmap_want(on_screen && !is_background(depth), position, bias_direction, settings.cascade_count, settings.resolution, settings.anchor, settings.select_half, settings.wanted_capacity);
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @type {WebGPUStruct}
3
+ */
4
+ export const PROBE_WANT_LATE_SETTINGS: WebGPUStruct;
5
+ /**
6
+ * The keys wanted since the last lifetime, each once, as the late wants listed them.
7
+ * @type {ShaderResourceDescriptor}
8
+ */
9
+ export const PROBE_LATE_WANTED_READ_RESOURCE: ShaderResourceDescriptor;
10
+ /**
11
+ * A bit a key of the late list, cleared as the key is taken.
12
+ * @type {ShaderResourceDescriptor}
13
+ */
14
+ export const PROBE_LATE_WANTED_BITS_RESOURCE: ShaderResourceDescriptor;
15
+ /**
16
+ * The cage windows the late list's keys were written in: the levels of the frame before.
17
+ * @type {ShaderResourceDescriptor}
18
+ */
19
+ export const PROBE_LATE_LEVELS_RESOURCE: ShaderResourceDescriptor;
20
+ /**
21
+ * The late wants taken into the frame's (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): a thread a key of the late
22
+ * list, through a launch its count sizes.
23
+ *
24
+ * A reader whose surface is drawn after the frame's lifetime wants its probes into the late set, through
25
+ * `probe_clipmap_want` as any want does, and the next lifetime runs this between its own wants and admit. A key
26
+ * the frame's set lacks goes on its list; either way the key's late bit is cleared, which leaves the late bits
27
+ * empty, and the host empties the list.
28
+ *
29
+ * A key names a storage cell, and the lattice point it stands for is the one its writer's window held there. Where
30
+ * a window has moved since, the cell of a point it left stands for the point that came in across from it, which
31
+ * nothing wanted: a key is taken only where the present window's point is one the writer's window
32
+ * (`probe_late_levels`) held too.
33
+ *
34
+ * @type {ComputeShader}
35
+ */
36
+ export const shader_probe_clipmap_want_late: ComputeShader;
37
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
38
+ import { ShaderResourceDescriptor } from "../../../shader/resource/ShaderResourceDescriptor.js";
39
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
40
+ //# sourceMappingURL=shader_probe_clipmap_want_late.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_probe_clipmap_want_late.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.js"],"names":[],"mappings":"AAmBA;;GAEG;AACH,uCAFU,YAAY,CASM;AAE5B;;;GAGG;AACH,8CAFU,wBAAwB,CAEqG;AAEvI;;;GAGG;AACH,8CAFU,wBAAwB,CAEkH;AAEpJ;;;GAGG;AACH,yCAFU,wBAAwB,CAEmF;AAcrH;;;;;;;;;;;;;;;GAeG;AACH,6CAFU,aAAa,CAkDpB;6BAnH0B,sCAAsC;yCAJ1B,sDAAsD;8BADjE,kCAAkC"}
@@ -0,0 +1,126 @@
1
+ import { COLLECTION_U32_STRUCT_READ } from "../../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
2
+ import { chunk_collection_u32_append } from "../../../gpu_primitive/chunk_collection_u32_append.js";
3
+ import { chunk_clipmap_contains } from "../../../shader/chunk/clipmap/chunk_clipmap_contains.js";
4
+ import { CLIPMAP_LEVEL_ARRAY, CLIPMAP_LEVEL_STRUCT } from "../../../shader/chunk/clipmap/CLIPMAP_LEVEL_STRUCT.js";
5
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
6
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
7
+ import { ShaderResourceDescriptor } from "../../../shader/resource/ShaderResourceDescriptor.js";
8
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
9
+ import { atomic_u32, u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
10
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
11
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
12
+ import {
13
+ chunk_probe_clipmap,
14
+ PROBE_LEVELS_RESOURCE,
15
+ PROBE_WANTED_BITS_RESOURCE,
16
+ PROBE_WANTED_WRITE_RESOURCE
17
+ } from "./chunk_probe_clipmap.js";
18
+ import { PROBE_THREAD_WORKGROUP_SIZE } from "./PROBE_CLIPMAP.js";
19
+
20
+ /**
21
+ * @type {WebGPUStruct}
22
+ */
23
+ export const PROBE_WANT_LATE_SETTINGS = WebGPUStruct.from({
24
+ /** lattice points a cascade's window has a side */
25
+ resolution: u32,
26
+ /** what the frame's wanted list holds at most */
27
+ wanted_capacity: u32,
28
+ /** what the late list holds at most: every key */
29
+ late_capacity: u32,
30
+ }, "ProbeWantLateSettings");
31
+
32
+ /**
33
+ * The keys wanted since the last lifetime, each once, as the late wants listed them.
34
+ * @type {ShaderResourceDescriptor}
35
+ */
36
+ export const PROBE_LATE_WANTED_READ_RESOURCE = ShaderResourceDescriptor.storageBuffer("probe_late_wanted", COLLECTION_U32_STRUCT_READ);
37
+
38
+ /**
39
+ * A bit a key of the late list, cleared as the key is taken.
40
+ * @type {ShaderResourceDescriptor}
41
+ */
42
+ export const PROBE_LATE_WANTED_BITS_RESOURCE = ShaderResourceDescriptor.storageBuffer("probe_late_wanted_bits", WebGPUArray.from(atomic_u32), true);
43
+
44
+ /**
45
+ * The cage windows the late list's keys were written in: the levels of the frame before.
46
+ * @type {ShaderResourceDescriptor}
47
+ */
48
+ export const PROBE_LATE_LEVELS_RESOURCE = ShaderResourceDescriptor.uniform("probe_late_levels", CLIPMAP_LEVEL_ARRAY);
49
+
50
+ const resources = new ShaderResourceSetDescriptor();
51
+
52
+ resources.setImmediate("settings", PROBE_WANT_LATE_SETTINGS);
53
+
54
+ resources.createGroup()
55
+ .add(PROBE_LEVELS_RESOURCE)
56
+ .add(PROBE_LATE_LEVELS_RESOURCE)
57
+ .add(PROBE_LATE_WANTED_READ_RESOURCE)
58
+ .add(PROBE_LATE_WANTED_BITS_RESOURCE)
59
+ .add(PROBE_WANTED_BITS_RESOURCE)
60
+ .add(PROBE_WANTED_WRITE_RESOURCE);
61
+
62
+ /**
63
+ * The late wants taken into the frame's (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): a thread a key of the late
64
+ * list, through a launch its count sizes.
65
+ *
66
+ * A reader whose surface is drawn after the frame's lifetime wants its probes into the late set, through
67
+ * `probe_clipmap_want` as any want does, and the next lifetime runs this between its own wants and admit. A key
68
+ * the frame's set lacks goes on its list; either way the key's late bit is cleared, which leaves the late bits
69
+ * empty, and the host empties the list.
70
+ *
71
+ * A key names a storage cell, and the lattice point it stands for is the one its writer's window held there. Where
72
+ * a window has moved since, the cell of a point it left stands for the point that came in across from it, which
73
+ * nothing wanted: a key is taken only where the present window's point is one the writer's window
74
+ * (`probe_late_levels`) held too.
75
+ *
76
+ * @type {ComputeShader}
77
+ */
78
+ export const shader_probe_clipmap_want_late = ComputeShader.from({
79
+ label: "Probe Clipmap Want Late",
80
+ resources,
81
+ body: CodeChunk.from(
82
+ //language=WGSL
83
+ `
84
+ @compute @workgroup_size(${PROBE_THREAD_WORKGROUP_SIZE})
85
+ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
86
+ let index = id.x;
87
+ let listed = index < min(probe_late_wanted.count, settings.late_capacity);
88
+
89
+ var key = 0u;
90
+
91
+ if (listed) {
92
+ key = probe_late_wanted.elements[index];
93
+ }
94
+
95
+ let bit = 1u << (key & 31u);
96
+
97
+ var wants = false;
98
+
99
+ if (listed) {
100
+ atomicAnd(&probe_late_wanted_bits[key >> 5u], ~bit);
101
+
102
+ let cascade = probe_clipmap_key_cascade(key, settings.resolution);
103
+ let point = probe_clipmap_window_point(probe_clipmap_key_storage(key, settings.resolution), probe_levels[cascade].corner, settings.resolution);
104
+ let written = probe_late_levels[cascade];
105
+
106
+ // a lattice window is a point past its cage window along each axis
107
+ wants = clipmap_contains(point, written.corner, written.size + vec3<i32>(1));
108
+ }
109
+
110
+ var first = false;
111
+
112
+ if (wants) {
113
+ first = (atomicOr(&probe_wanted_bits[key >> 5u], bit) & bit) == 0u;
114
+ }
115
+
116
+ // every lane, so that the append stays in uniform control flow
117
+ collection_u32_append(&probe_wanted, first, key, settings.wanted_capacity);
118
+ }
119
+ `, [
120
+ chunk_probe_clipmap,
121
+ chunk_clipmap_contains,
122
+ chunk_collection_u32_append,
123
+ CLIPMAP_LEVEL_STRUCT.declaration_chunk,
124
+ COLLECTION_U32_STRUCT_READ.declaration_chunk,
125
+ ]),
126
+ });
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The meshlets' wants, counted (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): a thread a listed meshlet, through
3
+ * the launch that walks the list, as `shader_avboit_occupancy` runs over it. `output` receives, for each, the
4
+ * cages a reader anywhere inside its world box can read (`probe_clipmap_box_cage_count`), and the list's count;
5
+ * their prefix sums launch `shader_probe_clipmap_want_meshlets`, a thread a cage.
6
+ *
7
+ * `output` is a count and its elements, cleared at its count for a list of no meshlet; it holds a count for each
8
+ * meshlet it has room for, and names that many.
9
+ *
10
+ * @type {ComputeShader}
11
+ */
12
+ export const shader_probe_clipmap_want_meshlet_count: ComputeShader;
13
+ /**
14
+ * The meshlets' wants (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): a thread a cage a listed meshlet's readers
15
+ * can read, through the launch the prefix sums of `shader_probe_clipmap_want_meshlet_count` size
16
+ * (`shader_prefix_sum_to_command`). The wants of the probes a forward-shaded surface picks from, which no pixel
17
+ * of the G-buffer stands for: every fragment of a meshlet reads cages its box's blocks hold
18
+ * (`chunk_probe_clipmap_box_cages`), so wanting those leaves none of them without its probes.
19
+ *
20
+ * A thread finds its meshlet by its place in the sums, and its cage by its place among the meshlet's blocks,
21
+ * cascade by cascade. It wants the cage where a point near it can select its cascade
22
+ * (`probe_clipmap_cage_is_read`), the cage meets the meshlet's box as that lies in its own space
23
+ * (`probe_clipmap_cage_meets_box`), and it meets the view's frustum.
24
+ *
25
+ * What it wants is a superset of what the meshlet's surface crosses: a box holds cages the surface inside it
26
+ * does not reach, the more the larger and the less flat the meshlet is against its cascade's spacing. The
27
+ * threads a meshlet takes are its blocks' cages.
28
+ *
29
+ * The wanted list and bits it binds are whichever the pass is given: recorded after the frame's lifetime, the
30
+ * late ones (`GPUProbeClipmap.write_want_bindings`).
31
+ *
32
+ * @type {ComputeShader}
33
+ */
34
+ export const shader_probe_clipmap_want_meshlets: ComputeShader;
35
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
36
+ //# sourceMappingURL=shader_probe_clipmap_want_meshlets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_probe_clipmap_want_meshlets.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.js"],"names":[],"mappings":"AAwCA;;;;;;;;;;GAUG;AACH,sDAFU,aAAa,CAwCpB;AAgBH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,iDAFU,aAAa,CAgGpB;8BA9M2B,kCAAkC"}
@@ -0,0 +1,221 @@
1
+ import { CAMERA_UNIFORM_STRUCT } from "../../../camera/CAMERA_UNIFORM_STRUCT.js";
2
+ import { MESHLET_METADATA_STRUCT } from "../../../geometry/meshlet/encoding/MESHLET_METADATA_STRUCT.js";
3
+ import { COLLECTION_U32_STRUCT_READ } from "../../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
4
+ import { MESHLET_COLLECTION_STRUCT } from "../../../rasterize/MESHLET_COLLECTION_STRUCT.js";
5
+ import { chunk_scene_database_access } from "../../../scene/chunk_scene_database_access.js";
6
+ import { CLIPMAP_LEVEL_LIMIT } from "../../../shader/chunk/clipmap/CLIPMAP_LEVEL_STRUCT.js";
7
+ import { AABB3_STRUCT } from "../../../shader/chunk/geometry/aabb3/AABB3_STRUCT.js";
8
+ import { chunk_aabb3_intersects_frustum } from "../../../shader/chunk/geometry/aabb3/chunk_aabb3_intersects_frustum.js";
9
+ import { chunk_aabb3_project } from "../../../shader/chunk/geometry/aabb3/chunk_aabb3_project.js";
10
+ import { chunk_array_to_aabb3 } from "../../../shader/chunk/geometry/aabb3/chunk_array_to_aabb3.js";
11
+ import { chunk_folded_workgroup_index } from "../../../shader/chunk/grid/chunk_folded_workgroup_index.js";
12
+ import { chunk_lower_bound_branchless } from "../../../shader/chunk/math/chunk_lower_bound_branchless.js";
13
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
14
+ import { COMPUTE_SHADER_DEFAULT_GROUP_SIZE } from "../../../shader/COMPUTE_SHADER_DEFAULT_GROUP_SIZE.js";
15
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
16
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
17
+ import { u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
18
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
19
+ import {
20
+ chunk_probe_clipmap,
21
+ PROBE_LEVELS_RESOURCE,
22
+ PROBE_WANTED_BITS_RESOURCE,
23
+ PROBE_WANTED_WRITE_RESOURCE
24
+ } from "./chunk_probe_clipmap.js";
25
+ import { chunk_probe_clipmap_box_cages } from "./chunk_probe_clipmap_box_cages.js";
26
+ import { chunk_probe_clipmap_want } from "./chunk_probe_clipmap_want.js";
27
+ import { PROBE_RECEIVER_BIAS } from "./PROBE_CLIPMAP.js";
28
+ import { PROBE_WANT_SETTINGS } from "./shader_probe_clipmap_want.js";
29
+
30
+ const count_resources = new ShaderResourceSetDescriptor();
31
+
32
+ count_resources.setImmediate("settings", PROBE_WANT_SETTINGS);
33
+
34
+ count_resources.createGroup()
35
+ .addStorageBuffer("scene_database", WebGPUArray.from(u32))
36
+ .addStorageBuffer("meshlet_metadata", WebGPUArray.from(MESHLET_METADATA_STRUCT))
37
+ .addStorageBuffer("input", MESHLET_COLLECTION_STRUCT)
38
+ .addStorageBuffer("output", COLLECTION_U32_STRUCT_READ, true)
39
+ .add(PROBE_LEVELS_RESOURCE);
40
+
41
+ /**
42
+ * The meshlets' wants, counted (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): a thread a listed meshlet, through
43
+ * the launch that walks the list, as `shader_avboit_occupancy` runs over it. `output` receives, for each, the
44
+ * cages a reader anywhere inside its world box can read (`probe_clipmap_box_cage_count`), and the list's count;
45
+ * their prefix sums launch `shader_probe_clipmap_want_meshlets`, a thread a cage.
46
+ *
47
+ * `output` is a count and its elements, cleared at its count for a list of no meshlet; it holds a count for each
48
+ * meshlet it has room for, and names that many.
49
+ *
50
+ * @type {ComputeShader}
51
+ */
52
+ export const shader_probe_clipmap_want_meshlet_count = ComputeShader.from({
53
+ label: "Probe Clipmap Want Meshlets / count",
54
+ resources: count_resources,
55
+ body: CodeChunk.from(
56
+ //language=WGSL
57
+ `
58
+ @compute @workgroup_size(${COMPUTE_SHADER_DEFAULT_GROUP_SIZE})
59
+ fn main(
60
+ @builtin(workgroup_id) workgroup_id: vec3<u32>,
61
+ @builtin(local_invocation_index) lane: u32,
62
+ ) {
63
+ let index = folded_workgroup_index(workgroup_id) * ${COMPUTE_SHADER_DEFAULT_GROUP_SIZE}u + lane;
64
+ let listed = min(input.count, arrayLength(&output.elements));
65
+
66
+ if (index >= listed) {
67
+ return;
68
+ }
69
+
70
+ if (index == 0u) {
71
+ output.count = listed;
72
+ }
73
+
74
+ let meshlet = input.elements[index];
75
+ let mesh = scene_read_mesh(&scene_database, meshlet.mesh);
76
+ let node = scene_read_node(&scene_database, mesh.node);
77
+ // its world box, as the occupancy and the HZB filter take it
78
+ let box = aabb3_project(array_to_aabb3(meshlet_metadata[meshlet.index].bounds_box), node.global);
79
+
80
+ output.elements[index] = probe_clipmap_box_cage_count(box.min, box.max, settings.cascade_count, settings.anchor, settings.select_half);
81
+ }
82
+ `, [
83
+ chunk_folded_workgroup_index,
84
+ AABB3_STRUCT.declaration_chunk,
85
+ chunk_array_to_aabb3,
86
+ chunk_aabb3_project,
87
+ chunk_scene_database_access,
88
+ chunk_probe_clipmap_box_cages,
89
+ ]),
90
+ });
91
+
92
+ const want_resources = new ShaderResourceSetDescriptor();
93
+
94
+ want_resources.setImmediate("settings", PROBE_WANT_SETTINGS);
95
+
96
+ want_resources.createGroup()
97
+ .addUniform("camera", CAMERA_UNIFORM_STRUCT)
98
+ .addStorageBuffer("scene_database", WebGPUArray.from(u32))
99
+ .addStorageBuffer("meshlet_metadata", WebGPUArray.from(MESHLET_METADATA_STRUCT))
100
+ .addStorageBuffer("input", MESHLET_COLLECTION_STRUCT)
101
+ .addStorageBuffer("prefix_sums", COLLECTION_U32_STRUCT_READ)
102
+ .add(PROBE_LEVELS_RESOURCE)
103
+ .add(PROBE_WANTED_BITS_RESOURCE)
104
+ .add(PROBE_WANTED_WRITE_RESOURCE);
105
+
106
+ /**
107
+ * The meshlets' wants (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): a thread a cage a listed meshlet's readers
108
+ * can read, through the launch the prefix sums of `shader_probe_clipmap_want_meshlet_count` size
109
+ * (`shader_prefix_sum_to_command`). The wants of the probes a forward-shaded surface picks from, which no pixel
110
+ * of the G-buffer stands for: every fragment of a meshlet reads cages its box's blocks hold
111
+ * (`chunk_probe_clipmap_box_cages`), so wanting those leaves none of them without its probes.
112
+ *
113
+ * A thread finds its meshlet by its place in the sums, and its cage by its place among the meshlet's blocks,
114
+ * cascade by cascade. It wants the cage where a point near it can select its cascade
115
+ * (`probe_clipmap_cage_is_read`), the cage meets the meshlet's box as that lies in its own space
116
+ * (`probe_clipmap_cage_meets_box`), and it meets the view's frustum.
117
+ *
118
+ * What it wants is a superset of what the meshlet's surface crosses: a box holds cages the surface inside it
119
+ * does not reach, the more the larger and the less flat the meshlet is against its cascade's spacing. The
120
+ * threads a meshlet takes are its blocks' cages.
121
+ *
122
+ * The wanted list and bits it binds are whichever the pass is given: recorded after the frame's lifetime, the
123
+ * late ones (`GPUProbeClipmap.write_want_bindings`).
124
+ *
125
+ * @type {ComputeShader}
126
+ */
127
+ export const shader_probe_clipmap_want_meshlets = ComputeShader.from({
128
+ label: "Probe Clipmap Want Meshlets",
129
+ resources: want_resources,
130
+ body: CodeChunk.from(
131
+ //language=WGSL
132
+ `
133
+ @compute @workgroup_size(${COMPUTE_SHADER_DEFAULT_GROUP_SIZE})
134
+ fn main(
135
+ @builtin(workgroup_id) workgroup_id: vec3<u32>,
136
+ @builtin(local_invocation_index) lane: u32,
137
+ ) {
138
+ // the launch's workgroups are shader_prefix_sum_to_command's
139
+ let thread = folded_workgroup_index(workgroup_id) * ${COMPUTE_SHADER_DEFAULT_GROUP_SIZE}u + lane;
140
+ let listed = prefix_sums.count;
141
+
142
+ // the meshlet whose cages hold the thread: the first whose sum is past it
143
+ var meshlet_index = 0u;
144
+
145
+ if (listed > 0u) {
146
+ meshlet_index = lower_bound_branchless(&prefix_sums.elements, thread + 1u, listed);
147
+ }
148
+
149
+ var wants = meshlet_index < listed;
150
+ var local = thread;
151
+
152
+ if (wants && meshlet_index > 0u) {
153
+ local = thread - prefix_sums.elements[meshlet_index - 1u];
154
+ }
155
+
156
+ var cascade = 0u;
157
+ var cage = vec3<i32>(0);
158
+
159
+ if (wants) {
160
+ let meshlet = input.elements[meshlet_index];
161
+ let mesh = scene_read_mesh(&scene_database, meshlet.mesh);
162
+ let node = scene_read_node(&scene_database, mesh.node);
163
+ let local_box = array_to_aabb3(meshlet_metadata[meshlet.index].bounds_box);
164
+ let box = aabb3_project(local_box, node.global);
165
+
166
+ // its block, cascade by cascade, and its cage in the block
167
+ let cascades = probe_clipmap_box_cascades(box.min, box.max, settings.cascade_count, settings.anchor, settings.select_half);
168
+
169
+ var found = false;
170
+
171
+ for (var i = 0u; i < ${CLIPMAP_LEVEL_LIMIT}u; i++) {
172
+ let c = cascades.x + i;
173
+
174
+ if (c >= cascades.y) {
175
+ break;
176
+ }
177
+
178
+ let cages = probe_clipmap_box_cages(box.min, box.max, c, settings.anchor, settings.select_half);
179
+ let count = cages.dims.x * cages.dims.y * cages.dims.z;
180
+
181
+ if (local < count) {
182
+ cascade = c;
183
+ cage = cages.first + vec3<i32>(vec3<u32>(local % cages.dims.x, (local / cages.dims.x) % cages.dims.y, local / (cages.dims.x * cages.dims.y)));
184
+ found = true;
185
+
186
+ break;
187
+ }
188
+
189
+ local -= count;
190
+ }
191
+
192
+ wants = found
193
+ && probe_clipmap_cage_is_read(cascade, cage, settings.anchor, settings.select_half)
194
+ && probe_clipmap_cage_meets_box(cascade, cage, local_box.min, local_box.max, node.global);
195
+
196
+ if (wants) {
197
+ // grown by the bias, as the points that read it lie
198
+ let cell = probe_levels[cascade].cell_size;
199
+ let bias = ${PROBE_RECEIVER_BIAS} * cell;
200
+ let reach = ${AABB3_STRUCT.wgsl_ref}(vec3<f32>(cage) * cell - bias, vec3<f32>(cage + vec3<i32>(1)) * cell + bias);
201
+
202
+ wants = aabb3_intersects_frustum(reach, camera.frustum);
203
+ }
204
+ }
205
+
206
+ // every lane, so that the appends stay in uniform control flow
207
+ probe_clipmap_want_cage(wants, cascade, cage, settings.resolution, settings.wanted_capacity);
208
+ }
209
+ `, [
210
+ chunk_probe_clipmap,
211
+ chunk_folded_workgroup_index,
212
+ chunk_lower_bound_branchless,
213
+ AABB3_STRUCT.declaration_chunk,
214
+ chunk_array_to_aabb3,
215
+ chunk_aabb3_project,
216
+ chunk_aabb3_intersects_frustum,
217
+ chunk_scene_database_access,
218
+ chunk_probe_clipmap_box_cages,
219
+ chunk_probe_clipmap_want,
220
+ ]),
221
+ });
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Buckets entries are sorted into by age. An age's bucket is its count of binary digits: 0 the first, 1 the
3
+ * second, 2 and 3 the third, and the last everything from `2^(AGE_EVICTION_BUCKETS − 2)` on.
4
+ *
5
+ * @type {number}
6
+ */
7
+ export const AGE_EVICTION_BUCKETS: number;
8
+ /**
9
+ * Eviction from a pool by pressure, oldest first, with no sort: the entries a pool could give up are
10
+ * counted into buckets by age, a plan asks for as many as the pool is short of, from the oldest bucket
11
+ * down, and the next pass over the entries takes what the plan asks for.
12
+ *
13
+ * ```wgsl
14
+ * const AGE_EVICTION_BUCKETS: u32
15
+ * fn age_eviction_bucket(age: u32) -> u32
16
+ * fn age_eviction_plan(counters: ptr<storage, array<atomic<u32>>, read_write>, ages: u32, lacking: u32) -> vec2<u32>
17
+ * fn age_eviction_whole(counted: u32, buckets: u32) -> bool
18
+ * fn age_eviction_partial(counted: u32, buckets: u32) -> bool
19
+ * ```
20
+ *
21
+ * - `age_eviction_bucket`: the bucket of an age ({@link AGE_EVICTION_BUCKETS}).
22
+ * - `age_eviction_plan`: reads the `AGE_EVICTION_BUCKETS` counts at `counters[ages]` on, how many entries
23
+ * that could be evicted each bucket holds, and empties them. Returns the plan that frees `lacking`
24
+ * entries, oldest first: `x` buckets whole, from the oldest, and `y` entries of the bucket below them. A
25
+ * shortfall the counted entries cannot cover takes them all and no more: past the youngest bucket
26
+ * anything was counted in, nothing is asked for.
27
+ * - `age_eviction_whole`: whether a plan of `buckets` whole buckets takes every entry counted in bucket
28
+ * `counted`.
29
+ * - `age_eviction_partial`: whether bucket `counted` is the one the plan takes some of: the caller takes
30
+ * entries of it while its own count of them is under the plan's `y`.
31
+ *
32
+ * The plan is made from one pass's counts and used by the next, so an entry's `counted` is the bucket it
33
+ * was in when counted, `age_eviction_bucket(age − 1)` a frame on: an entry that has aged into an asked
34
+ * bucket since, uncounted, is not taken for it.
35
+ *
36
+ * @type {CodeChunk}
37
+ */
38
+ export const chunk_age_eviction: CodeChunk;
39
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
40
+ //# sourceMappingURL=chunk_age_eviction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_age_eviction.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,mCAFU,MAAM,CAEuB;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,iCAFU,SAAS,CA+CjB;0BArFwB,oCAAoC"}
@@ -0,0 +1,86 @@
1
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
2
+
3
+ /**
4
+ * Buckets entries are sorted into by age. An age's bucket is its count of binary digits: 0 the first, 1 the
5
+ * second, 2 and 3 the third, and the last everything from `2^(AGE_EVICTION_BUCKETS − 2)` on.
6
+ *
7
+ * @type {number}
8
+ */
9
+ export const AGE_EVICTION_BUCKETS = 32;
10
+
11
+ /**
12
+ * Eviction from a pool by pressure, oldest first, with no sort: the entries a pool could give up are
13
+ * counted into buckets by age, a plan asks for as many as the pool is short of, from the oldest bucket
14
+ * down, and the next pass over the entries takes what the plan asks for.
15
+ *
16
+ * ```wgsl
17
+ * const AGE_EVICTION_BUCKETS: u32
18
+ * fn age_eviction_bucket(age: u32) -> u32
19
+ * fn age_eviction_plan(counters: ptr<storage, array<atomic<u32>>, read_write>, ages: u32, lacking: u32) -> vec2<u32>
20
+ * fn age_eviction_whole(counted: u32, buckets: u32) -> bool
21
+ * fn age_eviction_partial(counted: u32, buckets: u32) -> bool
22
+ * ```
23
+ *
24
+ * - `age_eviction_bucket`: the bucket of an age ({@link AGE_EVICTION_BUCKETS}).
25
+ * - `age_eviction_plan`: reads the `AGE_EVICTION_BUCKETS` counts at `counters[ages]` on, how many entries
26
+ * that could be evicted each bucket holds, and empties them. Returns the plan that frees `lacking`
27
+ * entries, oldest first: `x` buckets whole, from the oldest, and `y` entries of the bucket below them. A
28
+ * shortfall the counted entries cannot cover takes them all and no more: past the youngest bucket
29
+ * anything was counted in, nothing is asked for.
30
+ * - `age_eviction_whole`: whether a plan of `buckets` whole buckets takes every entry counted in bucket
31
+ * `counted`.
32
+ * - `age_eviction_partial`: whether bucket `counted` is the one the plan takes some of: the caller takes
33
+ * entries of it while its own count of them is under the plan's `y`.
34
+ *
35
+ * The plan is made from one pass's counts and used by the next, so an entry's `counted` is the bucket it
36
+ * was in when counted, `age_eviction_bucket(age − 1)` a frame on: an entry that has aged into an asked
37
+ * bucket since, uncounted, is not taken for it.
38
+ *
39
+ * @type {CodeChunk}
40
+ */
41
+ export const chunk_age_eviction = CodeChunk.from(
42
+ //language=WGSL
43
+ `
44
+ const AGE_EVICTION_BUCKETS: u32 = ${AGE_EVICTION_BUCKETS}u;
45
+
46
+ fn age_eviction_bucket(age: u32) -> u32 {
47
+ return min(32u - countLeadingZeros(age), AGE_EVICTION_BUCKETS - 1u);
48
+ }
49
+
50
+ fn age_eviction_plan(counters: ptr<storage, array<atomic<u32>>, read_write>, ages: u32, lacking: u32) -> vec2<u32> {
51
+ var left = lacking;
52
+ var buckets = 0u;
53
+ var remaining = 0u;
54
+
55
+ for (var k = 0u; k < AGE_EVICTION_BUCKETS; k++) {
56
+ let at = ages + AGE_EVICTION_BUCKETS - 1u - k;
57
+ let aged = atomicLoad(&counters[at]);
58
+
59
+ atomicStore(&counters[at], 0u);
60
+
61
+ // a bucket nothing was counted in is taken only for an older one: what ages into a bucket below every
62
+ // entry counted is not asked for
63
+ if (left > 0u && aged > 0u) {
64
+ if (aged <= left) {
65
+ left -= aged;
66
+ buckets = k + 1u;
67
+ } else {
68
+ buckets = k;
69
+ remaining = left;
70
+ left = 0u;
71
+ }
72
+ }
73
+ }
74
+
75
+ return vec2<u32>(buckets, remaining);
76
+ }
77
+
78
+ fn age_eviction_whole(counted: u32, buckets: u32) -> bool {
79
+ return counted >= AGE_EVICTION_BUCKETS - min(buckets, AGE_EVICTION_BUCKETS);
80
+ }
81
+
82
+ fn age_eviction_partial(counted: u32, buckets: u32) -> bool {
83
+ return counted + 1u == AGE_EVICTION_BUCKETS - min(buckets, AGE_EVICTION_BUCKETS);
84
+ }
85
+ `
86
+ );