@woosh/meep-engine 3.59.0 → 3.60.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 (326) hide show
  1. package/package.json +1 -1
  2. package/src/shade/playground/probe_clipmap/index.html +12 -0
  3. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
  4. package/src/shade/playground/probe_clipmap/main.js +5 -0
  5. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  6. package/src/shade/renderer/Renderer.js +4 -6
  7. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +63 -1
  8. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  9. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +228 -16
  10. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +27 -4
  11. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  12. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +526 -23
  13. package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.d.ts +11 -0
  14. package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.d.ts.map +1 -0
  15. package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.js +21 -0
  16. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.d.ts +65 -0
  17. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.d.ts.map +1 -0
  18. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.js +376 -0
  19. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.d.ts +7 -3
  20. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.d.ts.map +1 -1
  21. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.js +70 -6
  22. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.d.ts +20 -0
  23. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.d.ts.map +1 -0
  24. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.js +80 -0
  25. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.d.ts +18 -0
  26. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.d.ts.map +1 -0
  27. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.js +113 -0
  28. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts +47 -0
  29. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts.map +1 -0
  30. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.js +80 -0
  31. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts +91 -0
  32. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts.map +1 -0
  33. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.js +902 -0
  34. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts +16 -0
  35. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts.map +1 -0
  36. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.js +67 -0
  37. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts +17 -0
  38. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts.map +1 -0
  39. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.js +145 -0
  40. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts +12 -0
  41. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts.map +1 -0
  42. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.js +105 -0
  43. package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.d.ts.map +1 -1
  44. package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.js +2 -1
  45. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +3 -9
  46. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  47. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +13 -31
  48. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +764 -48
  49. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +410 -0
  50. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +3 -2
  51. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  52. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +4 -3
  53. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +41 -17
  54. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  55. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +57 -33
  56. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts +11 -3
  57. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts.map +1 -1
  58. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.js +13 -4
  59. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +9 -18
  60. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  61. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +8 -10
  62. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.d.ts +12 -0
  63. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.d.ts.map +1 -1
  64. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.js +28 -0
  65. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +1 -29
  66. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  67. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +1 -74
  68. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.d.ts +161 -0
  69. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.d.ts.map +1 -0
  70. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.js +219 -0
  71. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts +1 -8
  72. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts.map +1 -1
  73. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.js +1 -9
  74. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.d.ts +40 -12
  75. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.d.ts.map +1 -1
  76. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.js +373 -31
  77. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts +2 -1
  78. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts.map +1 -1
  79. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js +2 -1
  80. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.d.ts +15 -8
  81. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.d.ts.map +1 -1
  82. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.js +28 -14
  83. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.d.ts +23 -0
  84. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.d.ts.map +1 -0
  85. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.js +66 -0
  86. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.d.ts +29 -0
  87. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.d.ts.map +1 -0
  88. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.js +210 -0
  89. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.d.ts +29 -0
  90. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.d.ts.map +1 -0
  91. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.js +86 -0
  92. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.d.ts +41 -0
  93. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.d.ts.map +1 -0
  94. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.js +439 -0
  95. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.d.ts +23 -0
  96. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.d.ts.map +1 -0
  97. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.js +135 -0
  98. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.d.ts +3 -1
  99. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.d.ts.map +1 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.js +12 -3
  101. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +21 -18
  102. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  103. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +254 -73
  104. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +149 -8
  105. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  106. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +181 -13
  107. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +179 -7
  108. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +412 -31
  110. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +4 -4
  111. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  112. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +4 -3
  113. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +36 -10
  114. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
  115. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +218 -29
  116. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts +5 -1
  117. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts.map +1 -1
  118. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +24 -14
  119. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +15 -6
  120. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  121. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +21 -22
  122. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.d.ts +36 -0
  123. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.d.ts.map +1 -0
  124. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.js +257 -0
  125. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts +18 -7
  126. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts.map +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +157 -51
  128. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.d.ts +23 -0
  129. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.d.ts.map +1 -0
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.js +110 -0
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +24 -2
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +90 -10
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts +45 -0
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts.map +1 -0
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.js +205 -0
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts +16 -3
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +55 -10
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +19 -4
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +60 -6
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts +4 -8
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +21 -36
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts +21 -14
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +100 -30
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts +6 -2
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts.map +1 -1
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.js +26 -10
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts +3 -2
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts.map +1 -1
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.js +12 -12
  156. package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.d.ts +10 -0
  157. package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.d.ts.map +1 -0
  158. package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.js +21 -0
  159. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts +5 -2
  160. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts.map +1 -1
  161. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.js +31 -23
  162. package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.d.ts +10 -0
  163. package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.d.ts.map +1 -0
  164. package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.js +22 -0
  165. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.d.ts +9 -0
  166. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.d.ts.map +1 -0
  167. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.js +18 -0
  168. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts +8 -3
  169. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts.map +1 -1
  170. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.js +41 -32
  171. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.d.ts +31 -0
  172. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.d.ts.map +1 -0
  173. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.js +71 -0
  174. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.d.ts +47 -0
  175. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.d.ts.map +1 -0
  176. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.js +210 -0
  177. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +5 -4
  178. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts.map +1 -1
  179. package/src/shade/renderer/gpu_primitive/sort/defs.js +5 -4
  180. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +56 -15
  181. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  182. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +410 -61
  183. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts +4 -1
  184. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
  185. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +16 -42
  186. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.d.ts +15 -0
  187. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.d.ts.map +1 -0
  188. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.js +60 -0
  189. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.d.ts +25 -0
  190. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.d.ts.map +1 -0
  191. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.js +89 -0
  192. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts +3 -8
  193. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
  194. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +28 -160
  195. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.d.ts +12 -0
  196. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.d.ts.map +1 -0
  197. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.js +74 -0
  198. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts +3 -1
  199. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts.map +1 -1
  200. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.js +387 -188
  201. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.js +1 -1
  202. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.js +1 -1
  203. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  204. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +90 -72
  205. package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.d.ts +5 -0
  206. package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.d.ts.map +1 -1
  207. package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.js +9 -0
  208. package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.d.ts +13 -0
  209. package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.d.ts.map +1 -0
  210. package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.js +14 -0
  211. package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.d.ts +10 -0
  212. package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.d.ts.map +1 -0
  213. package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.js +15 -0
  214. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.d.ts +4 -3
  215. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.d.ts.map +1 -1
  216. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.js +6 -5
  217. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.d.ts +17 -2
  218. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.d.ts.map +1 -1
  219. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.js +25 -57
  220. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.d.ts +13 -0
  221. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.d.ts.map +1 -0
  222. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.js +70 -0
  223. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.d.ts +10 -0
  224. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.d.ts.map +1 -0
  225. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.js +59 -0
  226. package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.d.ts +12 -0
  227. package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.d.ts.map +1 -0
  228. package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.js +49 -0
  229. package/src/shade/renderer/path_tracer/shader/chunk_ray_hit_to_opacity.d.ts.map +1 -1
  230. package/src/shade/renderer/path_tracer/shader/chunk_ray_hit_to_opacity.js +1 -0
  231. package/src/shade/renderer/path_tracer/shader/chunk_render_trace_path.d.ts.map +1 -1
  232. package/src/shade/renderer/path_tracer/shader/chunk_render_trace_path.js +1 -0
  233. package/src/shade/renderer/path_tracer/shader/chunk_sample_material.d.ts.map +1 -1
  234. package/src/shade/renderer/path_tracer/shader/chunk_sample_material.js +2 -1
  235. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts +7 -0
  236. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
  237. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +15 -6
  238. package/src/shade/renderer/scene/GPUSceneContext.d.ts +7 -1
  239. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  240. package/src/shade/renderer/scene/GPUSceneContext.js +26 -1
  241. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.d.ts +7 -7
  242. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.d.ts.map +1 -1
  243. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.js +262 -294
  244. package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.d.ts +9 -0
  245. package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.d.ts.map +1 -0
  246. package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.js +21 -0
  247. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +43 -0
  248. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -0
  249. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +87 -0
  250. package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.d.ts +7 -1
  251. package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.d.ts.map +1 -1
  252. package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.js +1 -1
  253. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.d.ts +21 -0
  254. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.d.ts.map +1 -0
  255. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.js +42 -0
  256. package/src/shade/renderer/wind/GPUSceneWind.d.ts +1 -1
  257. package/src/shade/wgsl/emulator/CPUBitmapData.d.ts +19 -0
  258. package/src/shade/wgsl/emulator/CPUBitmapData.d.ts.map +1 -1
  259. package/src/shade/wgsl/emulator/CPUBitmapData.js +27 -0
  260. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  261. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +39 -18
  262. package/src/view/elements/progress/segmented/GhostTrail.d.ts +56 -0
  263. package/src/view/elements/progress/segmented/GhostTrail.d.ts.map +1 -0
  264. package/src/view/elements/progress/segmented/GhostTrail.js +98 -0
  265. package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.d.ts +3 -1
  266. package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.d.ts.map +1 -1
  267. package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.js +3 -1
  268. package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.d.ts +11 -0
  269. package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.d.ts.map +1 -0
  270. package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.js +15 -0
  271. package/src/view/elements/progress/segmented/SegmentDefinition.d.ts +3 -0
  272. package/src/view/elements/progress/segmented/SegmentDefinition.d.ts.map +1 -1
  273. package/src/view/elements/progress/segmented/SegmentDefinition.js +3 -0
  274. package/src/view/elements/progress/segmented/SegmentTier.d.ts +38 -0
  275. package/src/view/elements/progress/segmented/SegmentTier.d.ts.map +1 -0
  276. package/src/view/elements/progress/segmented/SegmentTier.js +50 -0
  277. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts +155 -10
  278. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts.map +1 -1
  279. package/src/view/elements/progress/segmented/SegmentedResourceBarView.js +427 -101
  280. package/src/view/elements/progress/segmented/playground/index.html +78 -0
  281. package/src/view/elements/progress/segmented/playground/main.d.ts +2 -0
  282. package/src/view/elements/progress/segmented/playground/main.d.ts.map +1 -0
  283. package/src/view/elements/progress/segmented/playground/main.js +173 -0
  284. package/src/view/elements/progress/segmented/segment_cell_layout.d.ts +48 -0
  285. package/src/view/elements/progress/segmented/segment_cell_layout.d.ts.map +1 -0
  286. package/src/view/elements/progress/segmented/segment_cell_layout.js +75 -0
  287. package/src/view/elements/progress/segmented/segment_notch_place.d.ts +18 -0
  288. package/src/view/elements/progress/segmented/segment_notch_place.d.ts.map +1 -0
  289. package/src/view/elements/progress/segmented/segment_notch_place.js +28 -0
  290. package/src/view/elements/progress/segmented/segment_tick_positions.d.ts +32 -0
  291. package/src/view/elements/progress/segmented/segment_tick_positions.d.ts.map +1 -0
  292. package/src/view/elements/progress/segmented/segment_tick_positions.js +103 -0
  293. package/src/view/elements/progress/segmented/segmented-resource-bar.css +142 -0
  294. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.d.ts +0 -35
  295. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.d.ts.map +0 -1
  296. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.js +0 -238
  297. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts +0 -99
  298. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts.map +0 -1
  299. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.js +0 -139
  300. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts +0 -65
  301. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts.map +0 -1
  302. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.js +0 -393
  303. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts +0 -17
  304. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts.map +0 -1
  305. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.js +0 -36
  306. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts +0 -29
  307. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts.map +0 -1
  308. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.js +0 -108
  309. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts +0 -31
  310. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts.map +0 -1
  311. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.js +0 -113
  312. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts +0 -36
  313. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts.map +0 -1
  314. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.js +0 -85
  315. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts +0 -23
  316. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts.map +0 -1
  317. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.js +0 -273
  318. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts +0 -13
  319. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts.map +0 -1
  320. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.js +0 -151
  321. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts +0 -13
  322. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts.map +0 -1
  323. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.js +0 -133
  324. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts +0 -22
  325. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts.map +0 -1
  326. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.js +0 -135
@@ -1,7 +1,35 @@
1
1
  import { assert } from "../../../../../../core/assert.js";
2
+ import { ceilPowerOfTwo } from "../../../../../../core/binary/operations/ceilPowerOfTwo.js";
2
3
  import { BufferDescriptor } from "../../../../../descriptor/buffer/BufferDescriptor.js";
4
+ import { graph_read_buffer } from "../../../../buffer/graph_read_buffer.js";
5
+ import { graph_import_buffer } from "../../../../shader/graph/graph_import_buffer.js";
3
6
  import { BRICK_TAKE_CELL_DISPATCH } from "../BRICK_CLIPMAP.js";
4
- import { MESH_BRICK_STATISTIC_WORDS, shader_mesh_brick_provider } from "./shader_mesh_brick_provider.js";
7
+ import {
8
+ MESH_BRICK_ACCUMULATOR_WORDS,
9
+ MESH_BRICK_COUNTER_BATCH_GROUPS,
10
+ MESH_BRICK_COUNTER_BATCHES,
11
+ MESH_BRICK_COUNTER_RESOLVE_GROUPS,
12
+ MESH_BRICK_COUNTER_RESOLVES,
13
+ MESH_BRICK_COUNTER_ROUND_GROUPS,
14
+ MESH_BRICK_COUNTER_TASKS,
15
+ MESH_BRICK_COUNTER_WORDS,
16
+ MESH_BRICK_RECORD_WORDS,
17
+ MESH_BRICK_ROUND_LIMIT,
18
+ MESH_BRICK_ROUNDS,
19
+ MESH_BRICK_STATISTIC_BATCHES_PEAK,
20
+ MESH_BRICK_STATISTIC_RESOLVES_PEAK,
21
+ MESH_BRICK_STATISTIC_ROUNDS_SHORT,
22
+ MESH_BRICK_STATISTIC_TASKS_PEAK,
23
+ MESH_BRICK_STATISTIC_WORDS
24
+ } from "./MESH_BRICK.js";
25
+ import { shader_mesh_brick_batch } from "./shader_mesh_brick_batch.js";
26
+ import {
27
+ MESH_BRICK_COMMAND_CLEAR_NONE,
28
+ MESH_BRICK_COMMAND_WORDS,
29
+ shader_mesh_brick_command
30
+ } from "./shader_mesh_brick_command.js";
31
+ import { shader_mesh_brick_gather } from "./shader_mesh_brick_gather.js";
32
+ import { shader_mesh_brick_resolve } from "./shader_mesh_brick_resolve.js";
5
33
 
6
34
  /**
7
35
  * @typedef {import("../GPUBrickClipmap.js").BrickProviderContext} BrickProviderContext
@@ -9,30 +37,97 @@ import { MESH_BRICK_STATISTIC_WORDS, shader_mesh_brick_provider } from "./shader
9
37
  */
10
38
 
11
39
  /**
12
- * The world's bricks from the meshes' cached fields (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §7.7): a
13
- * {@link BrickProvider} like any plugin, registered first. Per taken cell, the instances in the SDF
14
- * world whose boxes reach it, each sampled at the level of its field that suits the cascade, merged
15
- * into the staging by the minimum of the bytes, with the nearest instance's row as each 2³ cell's
16
- * object.
40
+ * Task records a half of the task buffer starts with. Zorah's fill asks for at most a few hundred a
41
+ * round; the capacity follows the most asked for.
42
+ * @type {number}
43
+ */
44
+ const INITIAL_TASK_CAPACITY = 1024;
45
+
46
+ /**
47
+ * Batch records the batch buffer starts with: a batch for each of the default budget's cells. The
48
+ * capacity follows the most asked for.
49
+ * @type {number}
50
+ */
51
+ const INITIAL_BATCH_CAPACITY = 4096;
52
+
53
+ /**
54
+ * Which of the commands is the resolve's: past the batches' and the rounds'.
55
+ * @type {number}
56
+ */
57
+ const RESOLVE_COMMAND = MESH_BRICK_ROUND_LIMIT;
58
+
59
+ /**
60
+ * The world's bricks from the meshes' cached fields (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §7.7, as S9
61
+ * built it): a {@link BrickProvider} like any plugin, registered first. Every instance in the SDF world
62
+ * whose box comes within the band of a taken cell is sampled there, at the level of its field that
63
+ * suits the cascade, however many reach the cell.
64
+ *
65
+ * A frame is one pass of dispatches, every one sized by a count on the device:
66
+ * - **walks** (`shader_mesh_brick_gather`), {@link rounds} of them: the taken cells' TLAS walks from the
67
+ * root, a workgroup a cell, then the walks of what each round handed on;
68
+ * - **batches** (`shader_mesh_brick_batch`): a workgroup a batch of up to 64 rows the walks found,
69
+ * merged into the cell's accumulators by atomic maxima;
70
+ * - **resolve** (`shader_mesh_brick_resolve`): a workgroup a cell the walks listed, one a batch reached
71
+ * or a walk of which did not finish, merging its accumulators into the staging by the provider
72
+ * contract (§7.6), and asking again for a cell whose walk did not finish. Most taken cells have no
73
+ * instance near them, and are not listed;
74
+ * - **commands** (`shader_mesh_brick_command`), a thread before each dispatch but the walks from the
75
+ * root: what the passes before it asked for, as its dispatch.
17
76
  *
18
- * It reads the view's scene through the context: the TLAS over the mesh rows, the scene database and
19
- * the geometry caches. A cell's instances past {@link MESH_BRICK_INSTANCE_LIMIT} are dropped; they and
20
- * whatever the gather itself dropped are counted in {@link statistics}.
77
+ * What the device asked for past a capacity, and walks the last round could not finish, are counted in
78
+ * {@link statistics}. The counts are read back each frame, and a later frame grows what held work back:
79
+ * a buffer to the power of two at or past the most asked for, the rounds by one up to
80
+ * {@link MESH_BRICK_ROUND_LIMIT}. The cells that lost work are asked for again meanwhile, so nothing is
81
+ * lost for longer than the growth takes.
21
82
  */
22
83
  export class MeshSDFBrickProvider {
23
84
  /** @type {GPUDevice} */
24
85
  #device;
25
86
 
26
87
  /**
27
- * Counts that accumulate: instances dropped past the limit, candidates and subtrees the gather
28
- * dropped (`shader_mesh_brick_provider.js`).
88
+ * The statistics, then the frame's counters (`MESH_BRICK.js`).
89
+ * @type {GPUBuffer}
90
+ */
91
+ #counters;
92
+
93
+ /**
94
+ * The batches' command, one a round past the first, and the resolve's: {@link MESH_BRICK_COMMAND_WORDS}
95
+ * words each.
29
96
  * @type {GPUBuffer}
30
97
  */
31
- #statistics;
98
+ #commands;
99
+
100
+ /** @type {GPUBuffer|null} */
101
+ #tasks = null;
102
+ #task_capacity = INITIAL_TASK_CAPACITY;
32
103
 
33
- #settings = { ring_capacity: 0, resolution: 0 };
104
+ /** @type {GPUBuffer|null} */
105
+ #batches = null;
106
+ #batch_capacity = INITIAL_BATCH_CAPACITY;
107
+
108
+ /**
109
+ * The build slots' accumulators, zero when nothing reached them.
110
+ * @type {GPUBuffer|null}
111
+ */
112
+ #accumulators = null;
113
+ #accumulator_slots = 0;
114
+
115
+ /**
116
+ * The frame's cells for the resolve, a place a build slot.
117
+ * @type {GPUBuffer|null}
118
+ */
119
+ #resolves = null;
120
+
121
+ #rounds = MESH_BRICK_ROUNDS;
122
+
123
+ /** What the last readback found: the walks the last round could not finish so far. */
124
+ #rounds_short = 0;
125
+
126
+ #gather_settings = { ring_capacity: 0, resolution: 0, round: 0, last: 0, task_capacity: 0, batch_capacity: 0 };
127
+ #command_settings = { asked: 0, groups: 0, capacity: 0, peak: 0, clear: 0, command: 0 };
128
+ #batch_settings = { ring_capacity: 0, resolution: 0 };
34
129
  #bindings = {};
35
- #data = { take: -1, staging: -1 };
130
+ #data = { take: -1, staging: -1, counters: -1 };
36
131
 
37
132
  /**
38
133
  * The context of the frame being recorded, as its pass executes.
@@ -50,18 +145,55 @@ export class MeshSDFBrickProvider {
50
145
 
51
146
  this.#device = device;
52
147
 
53
- this.#statistics = device.createBuffer(BufferDescriptor.fromJSON({
54
- label: 'Probe clipmap / mesh brick statistics',
55
- size: 4 * MESH_BRICK_STATISTIC_WORDS,
56
- usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
148
+ this.#counters = device.createBuffer(BufferDescriptor.fromJSON({
149
+ label: 'Probe clipmap / mesh brick counters',
150
+ size: 4 * MESH_BRICK_COUNTER_WORDS,
151
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
152
+ }));
153
+
154
+ this.#commands = device.createBuffer(BufferDescriptor.fromJSON({
155
+ label: 'Probe clipmap / mesh brick commands',
156
+ size: 4 * MESH_BRICK_COMMAND_WORDS * (RESOLVE_COMMAND + 1),
157
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT,
57
158
  }));
159
+
160
+ this.#tasks = this.#create_records('mesh brick tasks', 2 * this.#task_capacity);
161
+ this.#batches = this.#create_records('mesh brick batches', this.#batch_capacity);
58
162
  }
59
163
 
60
164
  /**
165
+ * Counts that accumulate for the provider's life, {@link MESH_BRICK_STATISTIC_WORDS} words at the start
166
+ * of the buffer (`MESH_BRICK.js`): the records asked for and the ones past a capacity, walks left
167
+ * unfinished, cells asked for again, the most records a frame and a round asked for, and the most
168
+ * cells a frame listed for the resolve.
61
169
  * @returns {GPUBuffer}
62
170
  */
63
171
  get statistics() {
64
- return this.#statistics;
172
+ return this.#counters;
173
+ }
174
+
175
+ /**
176
+ * Rounds of walks a frame runs: two at first, one more each time the last round could not finish a walk.
177
+ * @returns {number}
178
+ */
179
+ get rounds() {
180
+ return this.#rounds;
181
+ }
182
+
183
+ /**
184
+ * Task records a half of the task buffer holds.
185
+ * @returns {number}
186
+ */
187
+ get task_capacity() {
188
+ return this.#task_capacity;
189
+ }
190
+
191
+ /**
192
+ * Batch records a frame can sample.
193
+ * @returns {number}
194
+ */
195
+ get batch_capacity() {
196
+ return this.#batch_capacity;
65
197
  }
66
198
 
67
199
  /**
@@ -71,54 +203,264 @@ export class MeshSDFBrickProvider {
71
203
  graph_write_bricks(graph, context) {
72
204
  assert.notOk(this.#destroyed, 'destroyed');
73
205
  assert.defined(context.scene, 'context.scene');
206
+ assert.isPositiveInteger(context.staging_capacity, 'context.staging_capacity');
207
+
208
+ this.#ensure_records();
209
+ this.#ensure_accumulators(context.staging_capacity);
74
210
 
75
211
  const data = this.#data;
76
212
  const pass = graph.add("Brick Clipmap Mesh Provider", data, this.#execute);
77
213
 
78
214
  data.take = pass.read(context.take);
79
215
  data.staging = pass.write(context.staging);
216
+ data.counters = pass.write(graph_import_buffer(graph, this.#counters, "mesh brick counters"));
80
217
 
81
218
  // the next provider and the store come after this one's merge
82
219
  context.staging = data.staging;
83
220
 
84
221
  this.#context = context;
222
+
223
+ // what held work back grows, from a later frame
224
+ const rounds = this.#rounds;
225
+
226
+ graph_read_buffer({ graph, buffer: data.counters, offset: 0, size: 4 * MESH_BRICK_STATISTIC_WORDS })
227
+ .then(reference => {
228
+ try {
229
+ if (!this.#destroyed) {
230
+ this.#apply_statistics(new Uint32Array(reference.getValue()), rounds);
231
+ }
232
+ } finally {
233
+ reference.release();
234
+ }
235
+ })
236
+ .catch(() => {
237
+ // a reading lost to a timeout or a lost device: the counts run on, and a later reading carries them
238
+ });
239
+ }
240
+
241
+ /**
242
+ * @param {Uint32Array} words the statistics, read back
243
+ * @param {number} rounds the rounds the frame they were read from ran
244
+ */
245
+ #apply_statistics(words, rounds) {
246
+ const short = words[MESH_BRICK_STATISTIC_ROUNDS_SHORT];
247
+
248
+ // one round more for each frame that ran out of them, not for the frames already in flight
249
+ if (short !== this.#rounds_short) {
250
+ this.#rounds_short = short;
251
+
252
+ if (rounds === this.#rounds) {
253
+ this.#rounds = Math.min(this.#rounds + 1, MESH_BRICK_ROUND_LIMIT);
254
+ }
255
+ }
256
+
257
+ this.#task_capacity = Math.max(this.#task_capacity, ceilPowerOfTwo(words[MESH_BRICK_STATISTIC_TASKS_PEAK]));
258
+ this.#batch_capacity = Math.max(this.#batch_capacity, ceilPowerOfTwo(words[MESH_BRICK_STATISTIC_BATCHES_PEAK]));
259
+ }
260
+
261
+ /**
262
+ * @param {string} name
263
+ * @param {number} records
264
+ * @returns {GPUBuffer}
265
+ */
266
+ #create_records(name, records) {
267
+ return this.#device.createBuffer(BufferDescriptor.fromJSON({
268
+ label: `Probe clipmap / ${name}`,
269
+ size: 4 * MESH_BRICK_RECORD_WORDS * records,
270
+ usage: GPUBufferUsage.STORAGE,
271
+ }));
272
+ }
273
+
274
+ /**
275
+ * Record buffers of the capacities asked for: the records live a frame, so nothing is copied.
276
+ */
277
+ #ensure_records() {
278
+ if (this.#tasks.size < 4 * MESH_BRICK_RECORD_WORDS * 2 * this.#task_capacity) {
279
+ this.#tasks.destroy();
280
+ this.#tasks = this.#create_records('mesh brick tasks', 2 * this.#task_capacity);
281
+ }
282
+
283
+ if (this.#batches.size < 4 * MESH_BRICK_RECORD_WORDS * this.#batch_capacity) {
284
+ this.#batches.destroy();
285
+ this.#batches = this.#create_records('mesh brick batches', this.#batch_capacity);
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Accumulators, and a place on the resolve's list, for every build slot the staging holds. A new
291
+ * accumulator buffer is zero, which is empty, and the resolve leaves what it merges at zero, so
292
+ * nothing is cleared.
293
+ *
294
+ * @param {number} slots
295
+ */
296
+ #ensure_accumulators(slots) {
297
+ if (this.#accumulators !== null && this.#accumulator_slots >= slots) {
298
+ return;
299
+ }
300
+
301
+ this.#accumulators?.destroy();
302
+ this.#accumulator_slots = slots;
303
+ this.#accumulators = this.#device.createBuffer(BufferDescriptor.fromJSON({
304
+ label: 'Probe clipmap / mesh brick accumulators',
305
+ size: 4 * MESH_BRICK_ACCUMULATOR_WORDS * slots,
306
+ usage: GPUBufferUsage.STORAGE,
307
+ }));
308
+
309
+ this.#resolves?.destroy();
310
+ this.#resolves = this.#device.createBuffer(BufferDescriptor.fromJSON({
311
+ label: 'Probe clipmap / mesh brick resolves',
312
+ size: 4 * slots,
313
+ usage: GPUBufferUsage.STORAGE,
314
+ }));
85
315
  }
86
316
 
87
317
  #execute = (data, resources, execution) => {
88
318
  const context = this.#context;
89
319
  const scene = context.scene;
320
+ const encoder = execution.encoder;
90
321
  const take = resources.get(data.take);
322
+ const counters = resources.get(data.counters);
323
+ const rounds = this.#rounds;
91
324
 
92
- const settings = this.#settings;
93
-
94
- settings.ring_capacity = context.ring_capacity;
95
- settings.resolution = context.resolution;
325
+ // the frame's counters start from nothing; the statistics before them run on
326
+ encoder.clearBuffer(counters, 4 * MESH_BRICK_COUNTER_BATCHES, 4 * (MESH_BRICK_COUNTER_WORDS - MESH_BRICK_COUNTER_BATCHES));
96
327
 
97
328
  const b = scene.geometries.sdf.write_bindings(this.#bindings);
98
329
 
99
- b.settings = settings;
100
330
  b.brick_take = take;
101
331
  b.brick_ring = context.ring;
102
- b.brick_staging = resources.get(data.staging);
103
332
  b.brick_levels = context.levels;
104
- b.mesh_brick_statistics = this.#statistics;
333
+ b.brick_staging = resources.get(data.staging);
105
334
  b.tlas = scene.tlas.buffer;
106
335
  b.scene_database = scene.scene_database_buffer;
336
+ b.mesh_brick_counters = counters;
337
+ b.mesh_brick_commands = this.#commands;
338
+ b.mesh_brick_tasks = this.#tasks;
339
+ b.mesh_brick_batches = this.#batches;
340
+ b.mesh_brick_accumulators = this.#accumulators;
341
+ b.mesh_brick_resolves = this.#resolves;
107
342
 
108
- shader_mesh_brick_provider.dispatchIndirect({
109
- encoder: execution.encoder,
343
+ const gather = this.#gather_settings;
344
+
345
+ gather.ring_capacity = context.ring_capacity;
346
+ gather.resolution = context.resolution;
347
+ gather.task_capacity = this.#task_capacity;
348
+ gather.batch_capacity = this.#batch_capacity;
349
+
350
+ for (let round = 0; round < rounds; round++) {
351
+ gather.round = round;
352
+ gather.last = round === rounds - 1 ? 1 : 0;
353
+
354
+ if (round === 0) {
355
+ b.settings = gather;
356
+
357
+ shader_mesh_brick_gather.dispatchIndirect({
358
+ encoder,
359
+ bindings: b,
360
+ command: take,
361
+ command_offset: 4 * BRICK_TAKE_CELL_DISPATCH,
362
+ });
363
+
364
+ continue;
365
+ }
366
+
367
+ // the half the round before wrote is this round's walks; the other half it writes, from 0
368
+ this.#record_command(encoder, b,
369
+ MESH_BRICK_COUNTER_TASKS + ((round - 1) & 1),
370
+ MESH_BRICK_COUNTER_ROUND_GROUPS,
371
+ this.#task_capacity,
372
+ MESH_BRICK_STATISTIC_TASKS_PEAK,
373
+ MESH_BRICK_COUNTER_TASKS + (round & 1),
374
+ round
375
+ );
376
+
377
+ b.settings = gather;
378
+
379
+ shader_mesh_brick_gather.dispatchIndirect({
380
+ encoder,
381
+ bindings: b,
382
+ command: this.#commands,
383
+ command_offset: 4 * MESH_BRICK_COMMAND_WORDS * round,
384
+ });
385
+ }
386
+
387
+ // the batches every round asked for, in the command before the rounds'
388
+ this.#record_command(encoder, b,
389
+ MESH_BRICK_COUNTER_BATCHES,
390
+ MESH_BRICK_COUNTER_BATCH_GROUPS,
391
+ this.#batch_capacity,
392
+ MESH_BRICK_STATISTIC_BATCHES_PEAK,
393
+ MESH_BRICK_COMMAND_CLEAR_NONE,
394
+ 0
395
+ );
396
+
397
+ const batch = this.#batch_settings;
398
+
399
+ batch.ring_capacity = context.ring_capacity;
400
+ batch.resolution = context.resolution;
401
+ b.settings = batch;
402
+
403
+ shader_mesh_brick_batch.dispatchIndirect({
404
+ encoder,
110
405
  bindings: b,
111
- command: take,
112
- command_offset: 4 * BRICK_TAKE_CELL_DISPATCH,
406
+ command: this.#commands,
407
+ command_offset: 0,
408
+ });
409
+
410
+ // the cells the walks listed, once every batch is in
411
+ this.#record_command(encoder, b,
412
+ MESH_BRICK_COUNTER_RESOLVES,
413
+ MESH_BRICK_COUNTER_RESOLVE_GROUPS,
414
+ this.#accumulator_slots,
415
+ MESH_BRICK_STATISTIC_RESOLVES_PEAK,
416
+ MESH_BRICK_COMMAND_CLEAR_NONE,
417
+ RESOLVE_COMMAND
418
+ );
419
+
420
+ shader_mesh_brick_resolve.dispatchIndirect({
421
+ encoder,
422
+ bindings: b,
423
+ command: this.#commands,
424
+ command_offset: 4 * MESH_BRICK_COMMAND_WORDS * RESOLVE_COMMAND,
113
425
  });
114
426
  };
115
427
 
428
+ /**
429
+ * @param {GPUCommandEncoder} encoder
430
+ * @param {Object} b the bindings
431
+ * @param {number} asked
432
+ * @param {number} groups
433
+ * @param {number} capacity
434
+ * @param {number} peak
435
+ * @param {number} clear
436
+ * @param {number} command which of the commands
437
+ */
438
+ #record_command(encoder, b, asked, groups, capacity, peak, clear, command) {
439
+ const settings = this.#command_settings;
440
+
441
+ settings.asked = asked;
442
+ settings.groups = groups;
443
+ settings.capacity = capacity;
444
+ settings.peak = peak;
445
+ settings.clear = clear;
446
+ settings.command = MESH_BRICK_COMMAND_WORDS * command;
447
+
448
+ b.settings = settings;
449
+
450
+ shader_mesh_brick_command.dispatch({ encoder, bindings: b });
451
+ }
452
+
116
453
  destroy() {
117
454
  if (this.#destroyed) {
118
455
  return;
119
456
  }
120
457
 
121
458
  this.#destroyed = true;
122
- this.#statistics.destroy();
459
+ this.#counters.destroy();
460
+ this.#commands.destroy();
461
+ this.#tasks.destroy();
462
+ this.#batches.destroy();
463
+ this.#accumulators?.destroy();
464
+ this.#resolves?.destroy();
123
465
  }
124
466
  }
@@ -10,7 +10,8 @@
10
10
  * `mesh_brick_accept` is the gather's leaf filter, with `bounds` the row's world box and `voxel` the
11
11
  * cascade's: the row is in the SDF world, its geometry's field is resident (a skinned clone's through
12
12
  * its source's, the hook), and its box resolves in the cascade (`brick_provider_resolves`). A virtual
13
- * geometry has no header, so it is not resident and is the vgeo provider's (§7.8).
13
+ * geometry's field is the one baked for its proxy and adopted into it (§7.8), so its rows are taken as
14
+ * a mesh's are, once it is resident.
14
15
  *
15
16
  * `mesh_brick_instance` makes the instance the texels sample: the inverse of its transform, its box,
16
17
  * its smallest axis scale, and the coarsest level of its field no coarser than the cascade,
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_mesh_brick_instance.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wCAFU,SAAS,CA4DZ;0BAtFmB,0CAA0C"}
1
+ {"version":3,"file":"chunk_mesh_brick_instance.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wCAFU,SAAS,CA4DZ;0BAvFmB,0CAA0C"}
@@ -19,7 +19,8 @@ import { MESH_BRICK_INSTANCE_STRUCT } from "./MESH_BRICK_INSTANCE_STRUCT.js";
19
19
  * `mesh_brick_accept` is the gather's leaf filter, with `bounds` the row's world box and `voxel` the
20
20
  * cascade's: the row is in the SDF world, its geometry's field is resident (a skinned clone's through
21
21
  * its source's, the hook), and its box resolves in the cascade (`brick_provider_resolves`). A virtual
22
- * geometry has no header, so it is not resident and is the vgeo provider's (§7.8).
22
+ * geometry's field is the one baked for its proxy and adopted into it (§7.8), so its rows are taken as
23
+ * a mesh's are, once it is resident.
23
24
  *
24
25
  * `mesh_brick_instance` makes the instance the texels sample: the inverse of its transform, its box,
25
26
  * its smallest axis scale, and the coarsest level of its field no coarser than the cascade,
@@ -1,21 +1,28 @@
1
1
  /**
2
2
  * A world brick texel's distance from the mesh provider's instances (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md
3
- * §7.7): the minimum over them of `sigma · mesh_sdf_sample(header, level, M⁻¹·p)`, and the row it
4
- * came from.
3
+ * §7.7): the minimum over them of `sigma · mesh_sdf_sample(header, level, M⁻¹·p)`, and the row it came
4
+ * from, `band` being the cascade's (the texel's byte is `brick_encode(distance, band)`).
5
5
  *
6
6
  * ```wgsl
7
7
  * struct MeshBrickTexel { distance: f32, row: u32 } // F32_MAX and 0 with no instance
8
- * fn mesh_brick_texel(p: vec3<f32>, count: u32) -> MeshBrickTexel
8
+ * fn mesh_brick_texel(p: vec3<f32>, count: u32, band: f32) -> MeshBrickTexel
9
9
  * ```
10
10
  *
11
+ * The row is the lowest of the instances whose distance encodes to the texel's byte: the nearest in
12
+ * the byte the staging keeps, and among equally near ones the lowest row, whatever order the instances
13
+ * come in. A cell's instances reach it in batches in whatever order the walk found them, so its
14
+ * objects are the same however they were split.
15
+ *
11
16
  * The instances come through a seam the enclosing shader defines, as the cooperative query's tree
12
- * does: `fn mesh_brick_instance_at(i: u32) -> MeshBrickInstance`. The provider's kernel answers from
17
+ * does: `fn mesh_brick_instance_at(i: u32) -> MeshBrickInstance`. The provider's batch answers from
13
18
  * workgroup memory; a test, from a buffer.
14
19
  *
15
- * The box test is UE's early-out: an instance whose box lies farther than the running minimum, or
16
- * than the surface when the minimum is inside one, cannot give less, and is not sampled. At coarse
17
- * cascades most instances are only this test. Per texel: at most `count` box tests, and one
18
- * transform, one indirection load and one tap an instance the test lets through. No triangle is read.
20
+ * The box test is UE's early-out, in bytes: an instance whose box's distance encodes past the least
21
+ * byte so far, or past the surface's byte when the least is inside one, cannot reach it, and is not
22
+ * sampled. A box that holds the texel is always sampled, a deeper instance included. At coarse cascades
23
+ * most instances are only this test. Per
24
+ * texel: at most `count` box tests, and one transform, one indirection load and one tap an instance
25
+ * the test lets through. No triangle is read.
19
26
  *
20
27
  * Reads `mesh_sdf_headers` and what `mesh_sdf_sample` reads.
21
28
  *
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_mesh_brick_texel.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qCAFU,SAAS,CA2CZ;0BAnEmB,0CAA0C"}
1
+ {"version":3,"file":"chunk_mesh_brick_texel.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qCAFU,SAAS,CAiDZ;0BAjFmB,0CAA0C"}
@@ -2,26 +2,34 @@ import { chunk_mesh_sdf_sample } from "../../../../geometry/sdf/chunk_mesh_sdf_s
2
2
  import { MESH_SDF_HEADERS_RESOURCE } from "../../../../geometry/sdf/MESH_SDF_RESOURCES.js";
3
3
  import { F32_MAX_DEFINITION } from "../../../../shader/chunk/math/F32_MAX_DEFINITION.js";
4
4
  import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
5
+ import { chunk_brick_object } from "../chunk_brick_object.js";
5
6
  import { MESH_BRICK_INSTANCE_STRUCT } from "./MESH_BRICK_INSTANCE_STRUCT.js";
6
7
 
7
8
  /**
8
9
  * A world brick texel's distance from the mesh provider's instances (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md
9
- * §7.7): the minimum over them of `sigma · mesh_sdf_sample(header, level, M⁻¹·p)`, and the row it
10
- * came from.
10
+ * §7.7): the minimum over them of `sigma · mesh_sdf_sample(header, level, M⁻¹·p)`, and the row it came
11
+ * from, `band` being the cascade's (the texel's byte is `brick_encode(distance, band)`).
11
12
  *
12
13
  * ```wgsl
13
14
  * struct MeshBrickTexel { distance: f32, row: u32 } // F32_MAX and 0 with no instance
14
- * fn mesh_brick_texel(p: vec3<f32>, count: u32) -> MeshBrickTexel
15
+ * fn mesh_brick_texel(p: vec3<f32>, count: u32, band: f32) -> MeshBrickTexel
15
16
  * ```
16
17
  *
18
+ * The row is the lowest of the instances whose distance encodes to the texel's byte: the nearest in
19
+ * the byte the staging keeps, and among equally near ones the lowest row, whatever order the instances
20
+ * come in. A cell's instances reach it in batches in whatever order the walk found them, so its
21
+ * objects are the same however they were split.
22
+ *
17
23
  * The instances come through a seam the enclosing shader defines, as the cooperative query's tree
18
- * does: `fn mesh_brick_instance_at(i: u32) -> MeshBrickInstance`. The provider's kernel answers from
24
+ * does: `fn mesh_brick_instance_at(i: u32) -> MeshBrickInstance`. The provider's batch answers from
19
25
  * workgroup memory; a test, from a buffer.
20
26
  *
21
- * The box test is UE's early-out: an instance whose box lies farther than the running minimum, or
22
- * than the surface when the minimum is inside one, cannot give less, and is not sampled. At coarse
23
- * cascades most instances are only this test. Per texel: at most `count` box tests, and one
24
- * transform, one indirection load and one tap an instance the test lets through. No triangle is read.
27
+ * The box test is UE's early-out, in bytes: an instance whose box's distance encodes past the least
28
+ * byte so far, or past the surface's byte when the least is inside one, cannot reach it, and is not
29
+ * sampled. A box that holds the texel is always sampled, a deeper instance included. At coarse cascades
30
+ * most instances are only this test. Per
31
+ * texel: at most `count` box tests, and one transform, one indirection load and one tap an instance
32
+ * the test lets through. No triangle is read.
25
33
  *
26
34
  * Reads `mesh_sdf_headers` and what `mesh_sdf_sample` reads.
27
35
  *
@@ -35,19 +43,24 @@ struct MeshBrickTexel {
35
43
  row: u32,
36
44
  }
37
45
 
38
- fn mesh_brick_texel(p: vec3<f32>, count: u32) -> MeshBrickTexel {
46
+ fn mesh_brick_texel(p: vec3<f32>, count: u32, band: f32) -> MeshBrickTexel {
39
47
  var best: MeshBrickTexel;
40
48
 
41
49
  best.distance = F32_MAX;
42
50
  best.row = 0u;
43
51
 
52
+ // the least byte and the lowest row at it, as the largest object key: 0 before any instance
53
+ var key = 0u;
54
+
44
55
  for (var i = 0u; i < count; i++) {
45
56
  let instance = mesh_brick_instance_at(i);
46
57
 
47
58
  // the box's distance: 0 inside it, where an instance's surface can still lie nearer
48
59
  let outside = max(max(instance.box_min - p, p - instance.box_max), vec3<f32>(0.0));
49
60
 
50
- if (length(outside) > max(best.distance, 0.0)) {
61
+ // nothing at least that far encodes below the least byte so far, or below the surface's when that
62
+ // is inside one; a tie in the byte is still sampled
63
+ if (key != 0u && brick_encode(length(outside), band) > max(brick_object_key_byte(key), brick_encode(0.0, band))) {
51
64
  continue;
52
65
  }
53
66
 
@@ -56,17 +69,18 @@ fn mesh_brick_texel(p: vec3<f32>, count: u32) -> MeshBrickTexel {
56
69
 
57
70
  let distance = instance.sigma * mesh_sdf_sample(mesh_sdf_headers[instance.geometry], instance.level, local);
58
71
 
59
- if (distance < best.distance) {
60
- best.distance = distance;
61
- best.row = instance.row;
62
- }
72
+ best.distance = min(best.distance, distance);
73
+ key = max(key, brick_object_key(brick_encode(distance, band), instance.row));
63
74
  }
64
75
 
76
+ best.row = select(0u, brick_object_key_row(key), key != 0u);
77
+
65
78
  return best;
66
79
  }
67
80
  `, [
68
81
  F32_MAX_DEFINITION,
69
82
  chunk_mesh_sdf_sample,
83
+ chunk_brick_object,
70
84
  MESH_BRICK_INSTANCE_STRUCT.declaration_chunk,
71
85
  ]);
72
86