@woosh/meep-engine 3.60.4 → 3.60.5

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 (379) hide show
  1. package/CHANGELOG.md +2602 -0
  2. package/CONTRIBUTING.md +7 -0
  3. package/MIGRATION_2_TO_3.md +136 -0
  4. package/SECURITY.md +4 -0
  5. package/editor/EditorCameraNavigation.d.ts +2 -1
  6. package/editor/EditorCameraNavigation.d.ts.map +1 -1
  7. package/editor/EditorCameraNavigation.js +51 -57
  8. package/package.json +6 -2
  9. package/src/engine/EngineHarness.d.ts +3 -9
  10. package/src/engine/EngineHarness.d.ts.map +1 -1
  11. package/src/engine/EngineHarness.js +6 -8
  12. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
  13. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
  14. package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
  15. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
  16. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
  17. package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
  18. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
  19. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
  20. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
  21. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
  22. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
  23. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
  24. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
  25. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
  26. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
  27. package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
  28. package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
  29. package/src/engine/graphics/ecs/water/Water.js +8 -0
  30. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  31. package/src/engine/graphics3/WaterSystem.js +731 -734
  32. package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
  33. package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
  34. package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
  35. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
  36. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  37. package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
  38. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
  39. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
  40. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
  41. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
  42. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
  43. package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
  44. package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
  45. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  46. package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
  47. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
  48. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
  49. package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
  50. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
  51. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
  52. package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
  53. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
  54. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
  55. package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
  56. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
  57. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
  58. package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
  59. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  60. package/src/shade/playground/water_refraction/README.md +5 -6
  61. package/src/shade/playground/water_refraction/index.html +1 -1
  62. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  63. package/src/shade/renderer/Renderer.js +7 -5
  64. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
  65. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
  66. package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
  67. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  68. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  69. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  70. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  71. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  72. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +2 -2
  73. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +2 -2
  74. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +2 -1
  75. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  76. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +18 -1
  77. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
  78. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
  79. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
  80. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
  81. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
  82. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
  83. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
  84. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
  85. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  86. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +1 -8
  87. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +5 -5
  88. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  89. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +10 -10
  90. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +1 -4
  91. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  92. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +1 -10
  93. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
  94. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
  95. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
  96. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
  98. package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
  99. package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
  100. package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
  101. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
  102. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
  103. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
  104. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
  105. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
  106. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
  107. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
  108. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  109. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
  110. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
  111. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
  112. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
  113. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
  114. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
  115. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
  116. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
  117. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
  118. package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
  119. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
  120. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  121. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
  122. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
  123. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
  124. package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
  125. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  126. package/src/shade/renderer/material/GPUMaterialManager.d.ts +7 -0
  127. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  128. package/src/shade/renderer/material/GPUMaterialManager.js +11 -0
  129. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
  130. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  131. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
  132. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  133. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
  134. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
  135. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  136. package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
  137. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
  138. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
  139. package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
  140. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  141. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  142. package/src/shade/renderer/water/shader_water.js +22 -13
  143. package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
  144. package/src/shade/renderer/water/shader_water_avboit.js +7 -7
  145. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
  146. package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
  147. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
  148. package/editor/REWORK_PLAN_2026_08.md +0 -692
  149. package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
  150. package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
  151. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
  152. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
  153. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
  154. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
  155. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
  156. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
  157. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
  158. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
  159. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
  160. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
  161. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
  162. package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
  163. package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
  164. package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
  165. package/src/REVIEW_2026_08_06/adv-core.md +0 -511
  166. package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
  167. package/src/REVIEW_2026_08_06/adv-view.md +0 -446
  168. package/src/REVIEW_2026_08_06/api-core.md +0 -296
  169. package/src/REVIEW_2026_08_06/api-engine.md +0 -195
  170. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
  171. package/src/REVIEW_2026_08_06/core-binary.md +0 -348
  172. package/src/REVIEW_2026_08_06/core-collection.md +0 -376
  173. package/src/REVIEW_2026_08_06/core-math.md +0 -221
  174. package/src/REVIEW_2026_08_06/core-process.md +0 -266
  175. package/src/REVIEW_2026_08_06/core-science.md +0 -223
  176. package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
  177. package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
  178. package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
  179. package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
  180. package/src/REVIEW_2026_08_06/engine-input.md +0 -197
  181. package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
  182. package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
  183. package/src/REVIEW_2026_08_06/generation.md +0 -176
  184. package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
  185. package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
  186. package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
  187. package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
  188. package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
  189. package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
  190. package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
  191. package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
  192. package/src/REVIEW_2026_08_06/view.md +0 -667
  193. package/src/REVIEW_2026_08_06.md +0 -610
  194. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
  195. package/src/core/bvh2/bvh3/NOTES.md +0 -2
  196. package/src/core/bvh8/NOTES.md +0 -63
  197. package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
  198. package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
  199. package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
  200. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
  201. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
  202. package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
  203. package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
  204. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
  205. package/src/core/geom/3d/gjk/NOTES.md +0 -8
  206. package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
  207. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
  208. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
  209. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
  210. package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
  211. package/src/engine/REVIEW_2026_07_03.md +0 -211
  212. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
  213. package/src/engine/control/first-person/DESIGN.md +0 -658
  214. package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
  215. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
  216. package/src/engine/control/first-person/TODO.md +0 -160
  217. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
  218. package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
  219. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
  220. package/src/engine/ecs/ik/PLAN.md +0 -179
  221. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
  222. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
  223. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
  224. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
  225. package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
  226. package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
  227. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
  228. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
  229. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
  230. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
  231. package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
  232. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
  233. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
  234. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
  235. package/src/engine/network/CONGESTION_CONTROL.md +0 -87
  236. package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
  237. package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
  238. package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
  239. package/src/engine/physics/cloth/PLAN.md +0 -3056
  240. package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
  241. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
  242. package/src/engine/physics/fluid/solver/NOTES.md +0 -46
  243. package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
  244. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
  245. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
  246. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
  247. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
  248. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
  249. package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
  250. package/src/format/image/avif/DECISIONS.md +0 -545
  251. package/src/format/image/jpeg/NOTES.md +0 -3
  252. package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
  253. package/src/generation/COORDINATES.md +0 -54
  254. package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
  255. package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
  256. package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
  257. package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
  258. package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
  259. package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
  260. package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
  261. package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
  262. package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
  263. package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
  264. package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
  265. package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
  266. package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
  267. package/src/shade/RENDERER_CONTRACT.md +0 -697
  268. package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
  269. package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
  270. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
  271. package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
  272. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
  273. package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
  274. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
  275. package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
  276. package/src/shade/renderer/NOTES.md +0 -78
  277. package/src/shade/renderer/PLAN.md +0 -8
  278. package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
  279. package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
  280. package/src/shade/renderer/atmosphere/NOTES.md +0 -6
  281. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
  282. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
  283. package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
  284. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
  285. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
  286. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
  287. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
  288. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
  289. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
  290. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
  291. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
  292. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
  293. package/src/shade/renderer/camera/orbital/README.md +0 -81
  294. package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
  295. package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
  296. package/src/shade/renderer/camera/orbital/index.js +0 -9
  297. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
  298. package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
  299. package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
  300. package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
  301. package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
  302. package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
  303. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
  304. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
  305. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
  306. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -481
  307. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
  308. package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
  309. package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
  310. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
  311. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
  312. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
  313. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
  314. package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -529
  315. package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
  316. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4306
  317. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
  318. package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
  319. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
  320. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
  321. package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
  322. package/src/shade/renderer/hiz/NOTES.md +0 -3
  323. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
  324. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
  325. package/src/shade/renderer/light/cluster/NOTES.md +0 -11
  326. package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
  327. package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
  328. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
  329. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
  330. package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
  331. package/src/shade/renderer/particles/DESIGN.md +0 -1011
  332. package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -280
  333. package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
  334. package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
  335. package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
  336. package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
  337. package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
  338. package/src/shade/renderer/postprocess/nss/NOTES.md +0 -332
  339. package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
  340. package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
  341. package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
  342. package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
  343. package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
  344. package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
  345. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
  346. package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
  347. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
  348. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
  349. package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
  350. package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
  351. package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -391
  352. package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -153
  353. package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
  354. package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
  355. package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
  356. package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
  357. package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
  358. package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
  359. package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
  360. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
  361. package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
  362. package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -927
  363. package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
  364. package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
  365. package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
  366. package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
  367. package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
  368. package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
  369. package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
  370. package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
  371. package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
  372. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
  373. package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -3
  374. package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
  375. package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
  376. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
  377. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
  378. package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
  379. package/src/shade/wgsl/NOTES.md +0 -4
@@ -1,410 +0,0 @@
1
- # Probe rays: a variable count per probe, sorted for coherence — scope
2
-
3
- 2026-10-30. Scoped against master at `309823e49`. Since built: stage 1 (`0ec7a5fc3`), stage 2
4
- (`b825bd46c`, its as-built note in the proposal's §8.6) and the sort's generalisation (`053a1c8ba`).
5
- The sorted rays were built, measured on both GPUs on Sponza and Emerald Square, and not shipped
6
- ("Measured" under §2). Nor were the local sorts that followed (chunks, bins, a hash control, within
7
- each probe, position bits); the trace list in the probes' Morton order ships instead ("Local sorts,
8
- measured" under §2).
9
-
10
- ## What was asked
11
-
12
- 1. **A variable number of rays per probe update, as Enshrouded does it.**
13
- - A probe whose short-term mean dominates (it is changing) takes more rays.
14
- - A converged probe sips rays, except at the regular uniform updates that keep its depth and its
15
- estimator fed.
16
- - A DEAD probe shoots the minimum.
17
- 2. **Rays sorted (binned) for coherence** by one key: a short Morton code of the origin together
18
- with the octahedral direction.
19
-
20
- Enshrouded, as §2.1 records it from the talk's captions:
21
- - a new probe asks for 512 rays and decays fast to 16, rising again when it sees change;
22
- - requests are scaled down to the frame's budget, and rays are batched by a probe-index scan;
23
- - rays are sorted by position and direction, and hits by kind;
24
- - DEAD probes still trace 16 rays a frame.
25
-
26
- Sorting hits by kind was not asked for and stays out.
27
-
28
- ## Where the fixed R lives today
29
-
30
- Every pass that touches rays assumes R rays for each listed probe, at offset `k·R`.
31
-
32
- | Where | What assumes R |
33
- |---|---|
34
- | schedule, due | `U = ⌊ray_budget / R⌋` probes a frame; `T = ⌈P_w / U⌉` |
35
- | `shader_probe_clipmap_trace_command` | the ray dispatch is `traced × R` |
36
- | trace, light, shade, want_hits | ray thread → probe `ray / R`, its ray `ray % R` |
37
- | accumulate | `first_ray = k·R`; uniform rounds `R / n_r²`; guided runs inside `[0, R)` |
38
- | guide (weights, starts) | the hold `(64 − 2 − R/n_r²)/R`; the starts walk `R` rays |
39
- | `chunk_probe_clipmap_ray_texel` | the uniform ray↔texel map: powers of two, `R ∈ [n_r²/4, 4·n_r²]` |
40
- | project | classification's "was this update guided" test takes R |
41
- | `probe_rays` | sized `U·R` = the budget |
42
-
43
- The per-probe passes (relocate, the guide's three, accumulate, project, publish) cost by listed
44
- probe, not by ray. Accumulate was 0.43–0.68 ms on the iGPU at 512 probes. U keeps bounding them.
45
-
46
- ## 1. A variable ray count
47
-
48
- ### The update kinds and their rays
49
-
50
- | Update | Rays | Why |
51
- |---|---|---|
52
- | a probe's first (NEW) | `R_new` (Enshrouded 512, two a texel at n_r = 16), uniform | a new probe sees its whole sphere at once |
53
- | uniform: every 5th, every DEAD one | `R_u = n_r²`, one a texel, as today | keeps depth, classification and every texel's estimator fed |
54
- | guided | the probe's request, in `[R_min, R_max]` | change takes rays, a converged probe sips |
55
- | DEAD | `R_min`, uniform | see fork F4 |
56
-
57
- ### The request: from the probe, not the texel (measured)
58
-
59
- The estimator's per-texel inconsistency is the natural reading of "short-term mean dominates", but it
60
- cannot carry the request. Measured on the emulator through the shipped accumulate pass, eight streams,
61
- short blend 0.18:
62
- - a steady one-ray texel (σ = μ) reads 0.27 on average, 0.41 at p90;
63
- - after a ×2 step it reads 0.35 over updates 10–40, and after +30% it reads 0.29, both inside its
64
- own noise;
65
- - a texel lit by one ray in five reads 0.29 steady and 0.35–0.37 after either step;
66
- - at the blend of a texel the guide passes over (0.63) it reads 0.87 whatever happens.
67
-
68
- **Recommended signal: the same gap test, over the whole probe.** Take Σ over the probe's texels of
69
- (sample − long mean), luminance-weighted, against that sum's own noise, √Σ deviation².
70
- - Over 256 texels its noise is 16× smaller. A probe-wide +30% shift on one-ray texels is about
71
- 0.3·√256 ≈ 4.8 noise units in one update. That figure is derived, not measured; stage 0 measures it.
72
- - The accumulate thread already holds the sample, the mean and the deviation.
73
- - Projection's rows pass and probe pass already reduce per probe; they would carry the sum into the
74
- probe.
75
- - A NEW probe's request decays with its texels' count, Enshrouded's "decays fast".
76
- - The constants come from the measured distributions of this signal (steady against changed), not
77
- from round numbers.
78
-
79
- Changing probes then take more rays, so their samples' deviation shrinks as 1/√rays. That is what
80
- the estimator's own catch-up needs to engage sooner on the post-load shift measured on 2026-10-30. It
81
- only helps if the request sees the change, which per-texel inconsistency does not.
82
-
83
- ### The budget, the offsets, the dispatch
84
-
85
- - **U stays `⌊budget / R_u⌋`**, so a frame of all-uniform updates fits exactly as it does today, and
86
- the period `T = ⌈P_w/U⌉` is unchanged.
87
- - **Guided requests fill what's left, scaled down when over budget** (Enshrouded's "requests scaled to
88
- the budget"). The scale comes from the previous frame's demand, so one scan suffices.
89
- - **Offsets come from one exclusive scan** of the listed probes' ray counts (Enshrouded's
90
- "probe-index scan"):
91
- - `graph_prefix_scan_csdldf`, ≤ U elements, indirect over the list's count;
92
- - it gives each probe's first ray and the frame's total;
93
- - the ray dispatch is built from the total, the way the mesh expansion does it with
94
- `shader_prefix_sum_to_command`.
95
- - **A ray finds its probe by `lower_bound_branchless` over the offsets**: the mesh expansion's chunk,
96
- at most log₂U + 1 steps.
97
- - **The request's storage:** the record is full (64 B; `sh` takes bytes 32–63), and `screen` is a u32
98
- holding one bit. The request packs into its upper bits (fork F6).
99
- - **In a converged scene, guided updates run at R_min**, so the frame traces fewer rays than the
100
- budget. The saving is trace time: 6.8–7.6 ms on the iGPU and 0.34–0.47 ms on the 4090 at Sponza
101
- today (guiding's paired numbers).
102
-
103
- ### Forks
104
-
105
- - **F1. Schedule: keep the period, vary rays per update (recommended)**, rather than Enshrouded's
106
- every probe every frame. The per-probe passes scale with listed probes. Accumulate at 512 probes on
107
- the iGPU is 0.43–0.68 ms, so all 4,600 of Sponza's probes every frame would be about 4–6 ms
108
- (derived).
109
- - **F2. Over budget: scale the guided requests (recommended)**, rather than stretching T. Scaling
110
- keeps every probe's cadence, including the changing ones'.
111
- - **F3. Weigh a sample by its rays in the estimator (recommended, same stage).** Measured in the
112
- review: one one-ray uniform sample every 5th update, mixed into a 16-ray guided stream, raised the
113
- long mean's error 4.1 → 7.3% at β 0.18. Variable rays widen the spread from 0 to 64 rays a texel.
114
- The reference estimator has no weights, so this is measured on the emulator before it lands.
115
- - **F4. DEAD: every period at R_min (recommended)**, against today's every 8 periods at R.
116
- - It reacts 8× sooner for fewer rays.
117
- - R_min comes from the classification's tolerance. The back-face share's binomial deviation at the
118
- 25% threshold is ±11% at 16 rays, ±6% at 48 and ±5% at 64.
119
- - Below n_r²/4 rays the uniform map's assertion lifts; the spread map already covers every texel
120
- over n_r²/R updates.
121
- - **F5. R_max:** bounded by the 64-a-texel gather (`PROBE_TEXEL_RAYS`), by the depth limit
122
- `R ≤ 64·n_d²`, and by the budget. Its value comes from stage 2's measurement.
123
- - **F6. The request's storage:** pack it into `screen` (recommended), or grow the record to 80 B.
124
-
125
- ## 2. Sorted rays
126
-
127
- ### Design
128
-
129
- - **Key, one u32:**
130
- - origin: the Morton code of the probe's lattice coordinate inside its cascade's window (32³:
131
- 15 bits) plus its cascade (5 cascades: 3 bits);
132
- - direction: the ray's octahedral texel, coarsened to 8×8 bins (6 bits, UE's count);
133
- - 24 bits in all.
134
- - **Key pass:** a thread a ray over the frame's live total. The probe comes from `lower_bound` over
135
- the offsets, and the texel from the update's map (the uniform map, or the guide's search the trace
136
- already does). The value is the ray's index.
137
- - **Sort: `graph_radix_sort`, generalised, not copied.** It is the engine's sort, and the LBVH
138
- build is its one caller. Two changes:
139
- - it dispatches over a host element count today, which here would be the budget's capacity; it
140
- must follow the live total, indirect (the rule that GPU work follows the live count);
141
- - it always runs four 8-bit digit passes, 12 dispatches; a key-width option makes a 24-bit key
142
- three passes, 9 dispatches.
143
- - The batch pass's bitonic sort (≤ 64 rows in workgroup memory, inside a dispatch that runs anyway)
144
- is a different scale and is not a candidate.
145
- - **Consumers:** trace, light and shade take `ray = order[thread]`. Their outputs stay at the ray's
146
- index, so want_hits, accumulate and projection do not change.
147
- - **Layout fork, measured in stage 0:**
148
- - direction-major: binning 64 directions, with Morton position a todo;
149
- - origin-major: today's grouping by probe, with directions ordered within it;
150
- - interleaved.
151
-
152
- ### Not known; stage 0 measures it
153
-
154
- - The sort's cost at the budget, 131,072 keys, on both GPUs. No measurement is recorded.
155
- - Trace, light and shade time in sorted order against today's. Today a 64-lane wave is one probe's
156
- origin over four octahedral rows (uniform) or a run of the walk (guided).
157
- - The scattered writes: sorted threads write 28-B records at the ray's index.
158
- - Context: S3f's incoherent rays cost about 18× a coherent screen ray on the 4090 and about 5× on the
159
- iGPU. That benchmark predates the probe ray layout.
160
-
161
- ### Key layouts to measure (Alex, 2026-10-30)
162
-
163
- Four keys, plus today's unsorted order as the baseline. Each is timed as its whole cost: key pass,
164
- sort, trace, light and shade. Both GPUs, paired in one process (the key pass swapped by pipeline),
165
- Sponza with the caches resident. The direction bin is fixed at 8×8 octahedral bins (6 bits) for all
166
- four.
167
-
168
- **Two origin encodings:**
169
- - **O1, per cascade:** the Morton code of the probe's lattice coordinate inside its own cascade's
170
- window, 5 bits an axis at 32³ (15 bits), with the cascade's 3 bits above it. 18 bits.
171
- - **O2, one domain:** the Morton code of the probe's position inside the coarsest cascade's window,
172
- with no cascade bits.
173
- - That window spans 2^(C−1)·32 cascade-0 spacings: 512 at C = 5.
174
- - Telling cascade-0 probes apart takes 9 bits an axis (27). Beside 6 direction bits that is 33, so
175
- O2 takes 8 bits an axis (24): a cell of two cascade-0 spacings, where a pair of cascade-0 probes
176
- can share a code.
177
-
178
- **Two direction placements:**
179
- - **D-high, `[direction | origin]`:** rays bucket by direction across probes, as UE's 64 bins do.
180
- - **D-low, `[origin | direction]`:** rays bucket by probe position, in direction order within each.
181
-
182
- | Key | Bits | Radix passes |
183
- |---|---|---|
184
- | O1 D-high | 24 | 3 |
185
- | O1 D-low | 24 | 3 |
186
- | O2 D-high | 30 | 4 |
187
- | O2 D-low | 30 | 4 |
188
-
189
- The pass counts differ, so the sort's own cost is part of each key's comparison.
190
-
191
- ### Measured (2026-10-30): no key beats unsorted, so none ships
192
-
193
- Built as stage 3 lays it out, on top of stage 2's variable rays:
194
- - a key pass, a thread of the rays' launch, which finds each ray's texel as the trace does;
195
- - `graph_radix_sort` over the launch's threads, counted on the device (the ray command writes them),
196
- with the threads past the last ray keyed past every ray, so that they sort to the end in their own
197
- order;
198
- - trace, shade and light take `ray = order[thread]`.
199
-
200
- **How it was measured.** Sponza, and NVIDIA's Emerald Square (day, 2.69M triangles, 230 m a side;
201
- textures held to 1024² on the iGPU). The caches were resident, the clock at 60 Hz, and the camera and
202
- the light still. Emerald was measured from two views: down an avenue at 1.7 m, and from 29 m over the
203
- square. Each round ran every arm once in a seeded shuffled order: 8 frames unmeasured, then 24
204
- measured. There were 8 rounds on the 4090 and 4 on the iGPU. Two of the arms are unsorted, and their
205
- agreement is the noise. "Unsorted" runs the key pass as an identity, writing each thread's own index.
206
-
207
- The figures are the GPU's busy time from relocation's start to the light pass's end, a frame, in µs,
208
- as means. A frame's rays swing with the schedule's turn, between about 30k and 105k on Emerald. A
209
- median taken category by category picks a different kind of frame for each category, and this
210
- section's first tables, medians, read a 3× faster trace beside a 13× slower sort. The sorted arms are
211
- given against the mean of the two unsorted runs.
212
-
213
- **At the rays variable rays leave** (a still scene, most probes sipping):
214
-
215
- | Scene, GPU | Rays a frame | Unsorted (two runs) | O1 D-high | O1 D-low | O2 D-high | O2 D-low |
216
- |---|---|---|---|---|---|---|
217
- | Emerald avenue, 4090 | ~33k | 588.6 / 600.3 | +76 | +75 | +103 | +112 |
218
- | Emerald overview, 4090 | ~29k | 412.0 / 407.7 | +91 | +79 | +96 | +101 |
219
- | Sponza, 4090 | ~51k | 834.1 / 880.7 | +90 | +130 | +205 | +190 |
220
- | Emerald avenue, iGPU | ~32k | 6,848 / 6,110 | +1,830 | +1,049 | +1,821 | +1,232 |
221
- | Sponza, iGPU | ~59k | 5,651 / 5,653 | +2,466 | +624 | +2,607 | +547 |
222
-
223
- **At about 120k rays a frame**, every update asked for at least 256 rays (one a texel at n_r = 16; a
224
- measurement-only floor), the budget's 131,072 scaling the rest:
225
-
226
- | Scene, GPU | Rays a frame | Unsorted (two runs) | O1 D-high | O1 D-low | O2 D-high | O2 D-low |
227
- |---|---|---|---|---|---|---|
228
- | Emerald avenue, 4090 | ~127k | 767.7 / 772.1 | +15 | +16 | +65 | +84 |
229
- | Emerald overview, 4090 | ~117k | 943.3 / 919.4 | +189 | +161 | +298 | +743 |
230
- | Sponza, 4090 | ~120k | 1,507 / 1,426 | +340 | +324 | +40 | +342 |
231
- | Emerald avenue, iGPU | ~125k | 15,317 / 15,358 | +2,877 | +429 | +4,101 | +1,521 |
232
- | Sponza, iGPU | ~123k | 11,603 / 11,546 | +4,485 | +1,248 | +4,401 | +1,803 |
233
-
234
- - **No key beats unsorted, on either GPU, in any scene or view, at either count.**
235
- - **The trace does gain at the higher count, on Emerald's avenue.** On the 4090 it drops 11% with O1
236
- D-high (618.5 → 549.5 µs; the unsorted runs agree within 0.5 µs). On the iGPU it drops 6% with O1
237
- D-low, and shade 11% (−763 and −232 µs).
238
- - Keying and sorting cost more than that: about 75 µs on the 4090 (13 dispatches, latency-bound), and
239
- on the iGPU 1.49 ms (the key pass 328 µs past the identity's, the sort 1.13 ms).
240
- - At the lower count the trace does not move on either GPU.
241
- - **Direction-major keys (D-high) slow shade and light on both GPUs**: on the iGPU by 20–70% across
242
- trace, shade and light. A ray's record, 28 bytes when measured (`PROBE_RAY_STRUCT`; 24 since its light became one RGB9E5
243
- word), stays at the ray's own index.
244
- - Sorted threads read and write those records out of order, about twice the 32-byte sectors a
245
- record.
246
- - A wave of one direction also reads the origins and records of many probes, and the light pass's
247
- probe taps around many hits.
248
- - **The 4090's overview and Sponza read high at 120k for every key:** their shade, sort and scans
249
- measure 2–4× the avenue's at the same count, with 30–170 µs of idle gaps inside the stretch. The
250
- direction of the result holds in every case; those cases' size is uncertain.
251
- - **A lead, since shipped** (below). Origin-major order's gain could be had without sorting rays: order the trace
252
- list, at most U probes, by the probes' Morton codes, and the rays' layout follows it.
253
- - Its measured upper bound is O1 D-low's change to trace, shade and light. On Emerald's avenue at
254
- 125k rays that is −1.0 ms of the iGPU's 15.3 ms, and −49 µs on the 4090. At the lower count, and
255
- on Sponza, it is about none.
256
- - **Not shipped.** The wiring is reverted. It is kept, with the measurement-only floor, as
257
- `stage3b_sorted_rays_v2.patch` and `stage3b_shader_probe_clipmap_ray_keys.js` in the session's
258
- scratchpad. The harness is `device/sortab.js` there. The sort's generalisation landed first
259
- (`053a1c8ba`: `key_bits` and the device count). The BVH build is its only caller, and that caller
260
- uses neither.
261
-
262
- ### Local sorts, measured (2026-10-30): every one loses; the probes' order ships
263
-
264
- After the global keys, cheaper orders were tried: sorting the rays inside a chunk of the launch, one
265
- workgroup a chunk, and sorting the trace list instead of the rays. All were measured the same way as
266
- above, at the 256-ray floor (131,072 rays a frame, every frame, so the arms compare like for like), 96
267
- to 120 measured frames an arm, as means against the mean of two unsorted runs. Unless a table says
268
- otherwise, the figures are the busy time from relocation to the light pass's end.
269
-
270
- **The local sort.** A workgroup takes a chunk of the launch's threads, packs each ray's key above its
271
- place in the chunk, and sorts them with the radix scatter's stable binary split, a bit a round. The
272
- rays move only within their chunk. Keyed by the ray's direction bin, as the trace finds its texel:
273
- 8×8 bins of the octahedral map (6 bits) or 4×4 (4 bits).
274
- "Probe order, then" runs the trace-list sort below first. iGPU, Emerald avenue / Sponza:
275
-
276
- | Order | 2048-ray chunks | 1024 | 512 |
277
- |---|---|---|---|
278
- | 8×8 bins | +19.0% / +21.1% | +14.9% / +16.3% | +9.9% / +13.8% |
279
- | 4×4 bins | +14.4% / +12.6% | +11.8% / +12.9% | +9.2% / +10.8% |
280
- | Probe order, then 8×8 | +9.9% / +12.9% | +7.8% / +9.4% | +8.0% / +5.6% |
281
- | Probe order, then 4×4 | +7.0% / +9.4% | +7.7% / +6.5% | +4.9% / +5.0% |
282
-
283
- Unsorted: 13,324 / 12,095 µs, its two runs 0.3% / 1.6% apart. The probes' order alone: −1.9% / −4.0%.
284
- - **Coarser bins and smaller chunks help, step by step, and none reaches unsorted.**
285
- - What the order costs, before the trace sees it: on the iGPU, the key pass takes 280–330 µs (each ray's
286
- texel found a second time; 15–34 µs as an identity), and the sort 114–123 µs at 6 bits and 86–92 at
287
- 4, rising to 179 and 130 at 512-ray chunks. On the 4090 the sort takes 7–10 µs, less at smaller chunks.
288
- - **The 4090 does not care.** Every arm is within ±60 µs of its 618–630 µs, both scenes.
289
-
290
- **The control: a hash key.** The same local sort keyed by a hash of the ray (PCG), as many bits as the
291
- bins: the same scatter of records and the same mixing of probes in a wave, and no grouping by
292
- direction. The trace on the iGPU, Emerald / Sponza, against unsorted's 11,473 / 8,581 µs:
293
-
294
- | Chunk and bins | Direction key | Hash key |
295
- |---|---|---|
296
- | 8×8, 2048 | +15% / +20% | +52% / +57% |
297
- | 4×4, 512 | +8% / +8% | +34% / +36% |
298
- | Probe order, then 4×4, 512 | +1% / +3% | +29% / +30% |
299
-
300
- - **Direction coherence is worth 2.3–4.2 ms of the iGPU's trace here.** What loses is mixing several
301
- probes' rays in one wave, which every chunk of more than one probe does.
302
- - Under the hash, shade and light slow too (shade +0.7 to +1.2 ms, Sponza's light up to +1.9 ms): their
303
- records and hits scatter with the rays. On the 4090 hash and direction are within ±60 µs of each
304
- other.
305
-
306
- **Within each probe.** Keyed by the probe's place in the list (4 bits) above the bin, in 512-ray chunks,
307
- so that each probe's rays sort by direction and no wave mixes probes. The trace on the iGPU moved
308
- −0.6% to +1.4% at 131k rays, and +1.0% on Sponza's own schedule (57k rays): noise. The key and sort
309
- passes cost 470–680 µs on top. **The rays of one probe already share their waves, walking the map's
310
- texels in rows** (a uniform update `ray % texels`, a guided one the guide's walk), so a ray sort has
311
- nothing left to gain.
312
-
313
- **Position bits above the bin (Alex).** Probe order first, then a local sort in 2048-ray chunks keyed by
314
- 12 bits of the probe's Morton code past its low b bits, above the 8×8 bin: the probes of one 2^b-point
315
- block of the lattice mix and sort by direction together, and no others. Measured on `f12f7858c`
316
- (hits shadowed by traced rays). iGPU, Sponza / Emerald, busy (trace):
317
-
318
- | Mixing | Busy | Trace |
319
- |---|---|---|
320
- | b = 0, no probes mix | +4.1% / +3.4% | −0.6% / −1.7% |
321
- | b = 3, 2×2×2 blocks | +5.6% / +4.3% | +1.0% / −0.8% |
322
- | b = 6, 4×4×4 blocks | +9.6% / +8.4% | +4.9% / +3.4% |
323
- | Direction only | +13.0% / +11.2% | +10.1% / +7.9% |
324
- | Probe order alone | −1.9% / −1.4% | −1.5% / −1.4% |
325
-
326
- The trace follows the mixing and tops out at the probes' order's own; the key pass (about 300 µs) and the
327
- 18-bit sort (about 325 µs) come on top. 4090: every arm −1.7% to +7.1%.
328
-
329
- **With traced hit shadows** (`f12f7858c`: a sun ray and a local light's ray from every hit), the local
330
- sorts were measured again: iGPU Sponza / Emerald, 8×8 in 2048s +22.1% / +18.4%, probe order then 4×4 in
331
- 512s +5.9% / +6.3%, within each probe +5.2% / +4.1%, probe order alone −2.2% / −1.0%; 4090 +1% to +7%,
332
- probe order −0.4% to −1.8%. Unchanged: the secondary rays gain nothing from grouping the primaries.
333
-
334
- **The probes' order ships** (`shader_probe_clipmap_order.js`). After the due passes list the frame's
335
- updates, a workgroup a run of 1,024 listed probes sorts its run in place by the cascade and the Morton
336
- code of the probe's lattice point in the cascade's window (the bitonic workgroup sort,
337
- `chunk_sort_bitonic_workgroup`), dispatched through `PROBE_DISPATCH_ORDER`, which the update's command
338
- writes over the live count. Every pass after it reads the sorted list, the rays' layout among them, so
339
- neighbouring probes' rays run in neighbouring waves: the same blocks of the bricks and caches, a wave
340
- apart. Past one run the list is ordered within each run, not across them. The ray budget scales the
341
- requests in proportion, so the order changes no probe's rays.
342
-
343
- What it measured before shipping, iGPU at 131k rays, across five batches: Emerald −249, −510, −311,
344
- −130, −181 µs (1.0–3.6%); Sponza −479, −340, −267, −226 µs, and one batch +475. On the schedule's own
345
- counts, Sponza −109 and −171 µs. On the 4090, −58 to +37 µs: level. Its cost, a one-workgroup split sort
346
- in the measurement, was 14–18 µs.
347
-
348
- **As shipped, on the schedule's own counts** (no floor; 6 rounds, 144 frames an arm; the pass dispatched
349
- or skipped, each twice; the busy stretch, mean of each pair):
350
-
351
- | Scene, GPU | Rays a frame | Skipped | Ordered | Change | Pairs apart (skipped / ordered) |
352
- |---|---|---|---|---|---|
353
- | Sponza, iGPU | ~54k | 5,618 | 5,438 | −180 µs (−3.2%), trace −2.4% | 47 / 35 |
354
- | Emerald avenue, iGPU | 40–59k | 5,485 | 5,510 | +25 µs, noise | 390 / 150 |
355
- | Emerald avenue, 4090 | ~51k | 495 | 479 | −16 µs (−3.2%) | 19 / 19 |
356
- | Sponza, 4090 | ~55k | 500 | 508 | +7 µs, noise | 4 / 46 |
357
-
358
- - The pass takes 10.4–12.7 µs on both GPUs.
359
- - Read back on both GPUs after a frame, every run is in its keys' order and a permutation of the list
360
- (512 of 512 distinct).
361
- - Emerald's rays swing with the schedule's turn (40–59k between its blocks), which is why its
362
- floor-free pairs sit hundreds of µs apart.
363
-
364
- The measurement wiring is kept in the session's scratchpad, not the tree: `stage3e_local_sort_control_within.patch`
365
- (chunks, bins, the hash control, within-probe; for `c4d54e2cb`), `stage3f_sorts_on_f12f7858c.patch` and
366
- `stage3g_morton_bits_on_f12f7858c.patch` (the same and the position bits, for `f12f7858c`); the harness is
367
- `device/sortab.js`, and `device/orderab.js` A/Bs the shipped pass by skipping its dispatch.
368
-
369
- ## Stages
370
-
371
- 0. **Measure.** Scratchpad one-offs, both GPUs:
372
- - (a) the radix sort at 131,072 keys, 24 against 32 bits;
373
- - (b) the key pass, sort and permuted trace/light/shade, for the four keys of "Key layouts to
374
- measure" against today's order;
375
- - (c) the probe-level signal on the emulator: steady against +30% and ×2, one-ray and
376
- one-in-five texels.
377
-
378
- Decides whether sorting goes ahead, its layout, and the request's constants.
379
- 1. **Plumbing, with no behaviour change.**
380
- - A per-probe ray count and offset through every pass in the table above, and the ray dispatch
381
- over the live total.
382
- - Every request at R: bytes identical to master on the device.
383
- - The specs move to per-probe counts.
384
- 2. **Requests.**
385
- - NEW, uniform, guided and DEAD counts; the probe-level signal; budget scaling; the estimator's
386
- weighting by rays.
387
- - On the device: the post-residency dark spell (`timeline.mjs`), steady noise, and rays and
388
- trace time a frame.
389
- 3. **Sorting, if stage 0 says go.**
390
- - The radix sort's generalisation (indirect count, key width), pinned in its specs.
391
- - The key pass, and the permuted trace, light and shade.
392
- - A device A/B of the four keys against unsorted; the fastest key ships, and only if it beats
393
- unsorted on both GPUs.
394
-
395
- ## Reuse map
396
-
397
- | Need | Reused | Change |
398
- |---|---|---|
399
- | ray offsets and the frame's total | `graph_prefix_scan_csdldf` (out of place, indirect) | none |
400
- | the ray dispatch from the total | the mesh expansion's `shader_prefix_sum_to_command` pattern, `chunk_folded_dispatch` | none |
401
- | ray → probe | `chunk_lower_bound_branchless` | none |
402
- | the sort | `graph_radix_sort` | generalised: indirect count, key width |
403
- | origin Morton | `chunk_v3_morton_encode` | none |
404
- | direction bin | the probe's own octahedral texel | none |
405
- | the per-probe signal | projection's rows pass and probe pass | one more sum |
406
- | the request's storage | the record's `screen` word | packed |
407
- | the guided walk at R_k | the guide's three passes | R per probe |
408
-
409
- Duplication found along the way: the trace's `probe_trace_guided_position` is a binary search the
410
- lower-bound chunk could serve.
@@ -1,8 +0,0 @@
1
- NVidia's Spatial Hash Radiance Cache (SHaRC)
2
-
3
- References:
4
-
5
- * https://github.com/NVIDIA-RTX/SHARC/tree/025449a8cdf6739a5ec06c335a0639a7b4a269f4
6
- * SIGGRAPH 2020: "Real-Time Ray-Traced Ambient Occlusion of Complex Scenes using Spatial Hashing" by Pascal Gautron (
7
- NVIDIA)
8
- *