@driftengine/core 3.62.0 → 4.0.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 (428) hide show
  1. package/CHANGELOG.json +122 -0
  2. package/NOTICE +20 -0
  3. package/README.md +1 -1
  4. package/dist/core/loop.js +18 -2
  5. package/dist/core/storage.js +5 -0
  6. package/dist/geometry/meshBuilder.d.ts +1 -1
  7. package/dist/geometry/meshBuilder.js +6 -2
  8. package/dist/index.d.ts +70 -4
  9. package/dist/index.js +123 -2
  10. package/dist/input/input.js +6 -1
  11. package/dist/math/exact.d.ts +13 -3
  12. package/dist/math/exact.js +68 -3
  13. package/dist/math/frustum.d.ts +17 -2
  14. package/dist/math/frustum.js +24 -0
  15. package/dist/render/backend/api.d.ts +34 -1
  16. package/dist/render/backend/api.js +22 -1
  17. package/dist/render/backend/budget.d.ts +7 -6
  18. package/dist/render/backend/budget.js +7 -6
  19. package/dist/render/backend/createRenderer.d.ts +57 -0
  20. package/dist/render/backend/createRenderer.js +51 -2
  21. package/dist/render/backend/materialChanges.d.ts +41 -0
  22. package/dist/render/backend/materialChanges.js +38 -0
  23. package/dist/render/backend/select.js +8 -0
  24. package/dist/render/backend/webgl2/renderer.d.ts +80 -1
  25. package/dist/render/backend/webgl2/renderer.js +208 -10
  26. package/dist/render/backend/webgpu/buffers.d.ts +20 -1
  27. package/dist/render/backend/webgpu/buffers.js +116 -58
  28. package/dist/render/backend/webgpu/fieldCompose.d.ts +156 -0
  29. package/dist/render/backend/webgpu/fieldCompose.js +396 -0
  30. package/dist/render/backend/webgpu/giFieldPass.d.ts +66 -0
  31. package/dist/render/backend/webgpu/giFieldPass.js +137 -0
  32. package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +728 -0
  33. package/dist/render/backend/webgpu/gpuDrivenPass.js +2473 -0
  34. package/dist/render/backend/webgpu/linePass.d.ts +4 -14
  35. package/dist/render/backend/webgpu/linePass.js +4 -33
  36. package/dist/render/backend/webgpu/probeBake.d.ts +148 -0
  37. package/dist/render/backend/webgpu/probeBake.js +493 -0
  38. package/dist/render/backend/webgpu/renderer.d.ts +379 -24
  39. package/dist/render/backend/webgpu/renderer.js +1369 -76
  40. package/dist/render/backend/webgpu/scatterPass.js +15 -1
  41. package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +47 -14
  42. package/dist/render/backend/webgpu/surfaceTexturePass.js +128 -80
  43. package/dist/render/causticsRenderer.d.ts +3 -1
  44. package/dist/render/causticsRenderer.js +4 -1
  45. package/dist/render/depthConvention.d.ts +12 -0
  46. package/dist/render/depthConvention.js +14 -0
  47. package/dist/render/deviceFeatures.d.ts +32 -0
  48. package/dist/render/deviceFeatures.js +41 -0
  49. package/dist/render/fog.d.ts +79 -0
  50. package/dist/render/fog.js +138 -0
  51. package/dist/render/frame/alias.d.ts +30 -0
  52. package/dist/render/frame/alias.js +61 -0
  53. package/dist/render/frame/deps.d.ts +37 -0
  54. package/dist/render/frame/deps.js +122 -0
  55. package/dist/render/frame/flushGraph.d.ts +43 -0
  56. package/dist/render/frame/flushGraph.js +84 -0
  57. package/dist/render/frame/graphSchedule.d.ts +49 -0
  58. package/dist/render/frame/graphSchedule.js +120 -0
  59. package/dist/render/frame/index.d.ts +15 -0
  60. package/dist/render/frame/index.js +8 -0
  61. package/dist/render/frame/lifetime.d.ts +24 -0
  62. package/dist/render/frame/lifetime.js +36 -0
  63. package/dist/render/frame/passTimings.d.ts +42 -0
  64. package/dist/render/frame/passTimings.js +38 -0
  65. package/dist/render/frame/validate.d.ts +15 -0
  66. package/dist/render/frame/validate.js +22 -0
  67. package/dist/render/frame/virtual.d.ts +44 -0
  68. package/dist/render/frame/virtual.js +61 -0
  69. package/dist/render/gi/chain.d.ts +82 -0
  70. package/dist/render/gi/chain.js +135 -0
  71. package/dist/render/gi/denoise.d.ts +114 -0
  72. package/dist/render/gi/denoise.js +169 -0
  73. package/dist/render/gi/fieldScene.d.ts +125 -0
  74. package/dist/render/gi/fieldScene.js +219 -0
  75. package/dist/render/gi/globalField.d.ts +157 -0
  76. package/dist/render/gi/globalField.js +373 -0
  77. package/dist/render/gi/probeGridFit.d.ts +24 -0
  78. package/dist/render/gi/probeGridFit.js +71 -0
  79. package/dist/render/gi/probeTrace.d.ts +82 -0
  80. package/dist/render/gi/probeTrace.js +128 -0
  81. package/dist/render/gi/probeVolume.d.ts +136 -0
  82. package/dist/render/gi/probeVolume.js +191 -0
  83. package/dist/render/gi/reflection.d.ts +73 -0
  84. package/dist/render/gi/reflection.js +109 -0
  85. package/dist/render/gi/traceField.d.ts +91 -0
  86. package/dist/render/gi/traceField.js +129 -0
  87. package/dist/render/gi/traceScreen.d.ts +68 -0
  88. package/dist/render/gi/traceScreen.js +82 -0
  89. package/dist/render/gpuScene.d.ts +38 -0
  90. package/dist/render/gpuScene.js +41 -0
  91. package/dist/render/gpudriven/alphaTest.d.ts +28 -0
  92. package/dist/render/gpudriven/alphaTest.js +32 -0
  93. package/dist/render/gpudriven/clusterUpload.d.ts +59 -0
  94. package/dist/render/gpudriven/clusterUpload.js +75 -0
  95. package/dist/render/gpudriven/clusterWorld.d.ts +57 -0
  96. package/dist/render/gpudriven/clusterWorld.js +155 -0
  97. package/dist/render/gpudriven/compact.d.ts +51 -0
  98. package/dist/render/gpudriven/compact.js +68 -0
  99. package/dist/render/gpudriven/cullClusters.d.ts +129 -0
  100. package/dist/render/gpudriven/cullClusters.js +237 -0
  101. package/dist/render/gpudriven/decodeTables.d.ts +64 -0
  102. package/dist/render/gpudriven/decodeTables.js +219 -0
  103. package/dist/render/gpudriven/frustum.d.ts +25 -0
  104. package/dist/render/gpudriven/frustum.js +59 -0
  105. package/dist/render/gpudriven/geometryHarness.d.ts +15 -0
  106. package/dist/render/gpudriven/geometryHarness.js +31 -0
  107. package/dist/render/gpudriven/hzb.d.ts +60 -0
  108. package/dist/render/gpudriven/hzb.js +97 -0
  109. package/dist/render/gpudriven/ibl.d.ts +85 -0
  110. package/dist/render/gpudriven/ibl.js +129 -0
  111. package/dist/render/gpudriven/indirect.d.ts +67 -0
  112. package/dist/render/gpudriven/indirect.js +77 -0
  113. package/dist/render/gpudriven/instances.d.ts +43 -0
  114. package/dist/render/gpudriven/instances.js +172 -0
  115. package/dist/render/gpudriven/lit.d.ts +165 -0
  116. package/dist/render/gpudriven/lit.js +165 -0
  117. package/dist/render/gpudriven/lodCut.d.ts +28 -0
  118. package/dist/render/gpudriven/lodCut.js +38 -0
  119. package/dist/render/gpudriven/materialBin.d.ts +60 -0
  120. package/dist/render/gpudriven/materialBin.js +108 -0
  121. package/dist/render/gpudriven/materialTable.d.ts +88 -0
  122. package/dist/render/gpudriven/materialTable.js +115 -0
  123. package/dist/render/gpudriven/pipeline.d.ts +135 -0
  124. package/dist/render/gpudriven/pipeline.js +237 -0
  125. package/dist/render/gpudriven/rangeAlloc.d.ts +50 -0
  126. package/dist/render/gpudriven/rangeAlloc.js +112 -0
  127. package/dist/render/gpudriven/sceneUpload.d.ts +96 -0
  128. package/dist/render/gpudriven/sceneUpload.js +115 -0
  129. package/dist/render/gpudriven/shadeBins.d.ts +92 -0
  130. package/dist/render/gpudriven/shadeBins.js +182 -0
  131. package/dist/render/gpudriven/shadow.d.ts +136 -0
  132. package/dist/render/gpudriven/shadow.js +224 -0
  133. package/dist/render/gpudriven/shadowCamera.d.ts +87 -0
  134. package/dist/render/gpudriven/shadowCamera.js +345 -0
  135. package/dist/render/gpudriven/streamScene.d.ts +194 -0
  136. package/dist/render/gpudriven/streamScene.js +459 -0
  137. package/dist/render/gpudriven/surfaceFrame.d.ts +25 -0
  138. package/dist/render/gpudriven/surfaceFrame.js +51 -0
  139. package/dist/render/gpudriven/twoPhase.d.ts +122 -0
  140. package/dist/render/gpudriven/twoPhase.js +160 -0
  141. package/dist/render/gpudriven/visbuffer.d.ts +25 -0
  142. package/dist/render/gpudriven/visbuffer.js +37 -0
  143. package/dist/render/halfFloat.d.ts +10 -0
  144. package/dist/render/halfFloat.js +23 -4
  145. package/dist/render/inference/attentionTiled.d.ts +27 -0
  146. package/dist/render/inference/attentionTiled.js +117 -0
  147. package/dist/render/inference/denseKernels.d.ts +29 -0
  148. package/dist/render/inference/denseKernels.js +312 -0
  149. package/dist/render/inference/device.d.ts +21 -0
  150. package/dist/render/inference/device.js +32 -0
  151. package/dist/render/inference/deviceGraph.d.ts +34 -0
  152. package/dist/render/inference/deviceGraph.js +17 -0
  153. package/dist/render/inference/fuse.d.ts +15 -0
  154. package/dist/render/inference/fuse.js +37 -0
  155. package/dist/render/inference/kernelKit.d.ts +52 -0
  156. package/dist/render/inference/kernelKit.js +70 -0
  157. package/dist/render/inference/kernels.d.ts +3 -0
  158. package/dist/render/inference/kernels.js +11 -0
  159. package/dist/render/inference/plan.d.ts +13 -0
  160. package/dist/render/inference/plan.js +18 -0
  161. package/dist/render/inference/reuse.d.ts +39 -0
  162. package/dist/render/inference/reuse.js +65 -0
  163. package/dist/render/inference/runner.d.ts +31 -0
  164. package/dist/render/inference/runner.js +175 -0
  165. package/dist/render/inference/schedule.d.ts +39 -0
  166. package/dist/render/inference/schedule.js +59 -0
  167. package/dist/render/inference/shapeKernels.d.ts +10 -0
  168. package/dist/render/inference/shapeKernels.js +80 -0
  169. package/dist/render/inference/spatialKernels.d.ts +21 -0
  170. package/dist/render/inference/spatialKernels.js +179 -0
  171. package/dist/render/inference/splatRaster.wgsl.d.ts +75 -0
  172. package/dist/render/inference/splatRaster.wgsl.js +337 -0
  173. package/dist/render/inference/splatTiles.d.ts +79 -0
  174. package/dist/render/inference/splatTiles.js +161 -0
  175. package/dist/render/lineBatch.d.ts +2 -5
  176. package/dist/render/lineBatch.js +4 -24
  177. package/dist/render/mesh.d.ts +4 -0
  178. package/dist/render/mesh.js +45 -1
  179. package/dist/render/pass.d.ts +145 -8
  180. package/dist/render/prefilterEnvMap.d.ts +22 -0
  181. package/dist/render/prefilterEnvMap.js +31 -0
  182. package/dist/render/readback.d.ts +30 -0
  183. package/dist/render/readback.js +47 -0
  184. package/dist/render/recon/clamp.d.ts +36 -0
  185. package/dist/render/recon/clamp.js +92 -0
  186. package/dist/render/recon/disocclusion.d.ts +60 -0
  187. package/dist/render/recon/disocclusion.js +109 -0
  188. package/dist/render/recon/frameGen.d.ts +81 -0
  189. package/dist/render/recon/frameGen.js +150 -0
  190. package/dist/render/recon/frameSizes.d.ts +34 -0
  191. package/dist/render/recon/frameSizes.js +58 -0
  192. package/dist/render/recon/jitter.d.ts +60 -0
  193. package/dist/render/recon/jitter.js +118 -0
  194. package/dist/render/recon/motionVectors.d.ts +55 -0
  195. package/dist/render/recon/motionVectors.js +107 -0
  196. package/dist/render/recon/reproject.d.ts +41 -0
  197. package/dist/render/recon/reproject.js +131 -0
  198. package/dist/render/recon/resolve.d.ts +90 -0
  199. package/dist/render/recon/resolve.js +313 -0
  200. package/dist/render/recon/tier.d.ts +24 -0
  201. package/dist/render/recon/tier.js +8 -0
  202. package/dist/render/reflectionProbe.d.ts +26 -0
  203. package/dist/render/reflectionProbe.js +33 -0
  204. package/dist/render/renderQuality.d.ts +69 -0
  205. package/dist/render/renderQuality.js +22 -0
  206. package/dist/render/screenSpaceReflection.d.ts +23 -0
  207. package/dist/render/screenSpaceReflection.js +22 -3
  208. package/dist/render/sdfFont.js +2 -0
  209. package/dist/render/segmentQuads.d.ts +13 -0
  210. package/dist/render/segmentQuads.js +32 -0
  211. package/dist/render/shaders/flat/lobes.d.ts +27 -0
  212. package/dist/render/shaders/flat/lobes.js +33 -3
  213. package/dist/render/shaders/flat/preamble.d.ts +7 -0
  214. package/dist/render/shaders/flat/preamble.js +24 -1
  215. package/dist/render/shaders/flat/probeGrid.d.ts +1 -1
  216. package/dist/render/shaders/flat/probeGrid.js +71 -2
  217. package/dist/render/shaders/generated/flat.wgsl.d.ts +48 -8
  218. package/dist/render/shaders/generated/flat.wgsl.js +64 -24
  219. package/dist/render/shaders/gi/composeField.wgsl.d.ts +56 -0
  220. package/dist/render/shaders/gi/composeField.wgsl.js +231 -0
  221. package/dist/render/shaders/gi/marchField.wgsl.d.ts +30 -0
  222. package/dist/render/shaders/gi/marchField.wgsl.js +141 -0
  223. package/dist/render/shaders/gi/probeBake.wgsl.d.ts +113 -0
  224. package/dist/render/shaders/gi/probeBake.wgsl.js +635 -0
  225. package/dist/render/shaders/gi/probeTrace.wgsl.d.ts +72 -0
  226. package/dist/render/shaders/gi/probeTrace.wgsl.js +261 -0
  227. package/dist/render/shaders/gi/probeVolume.wgsl.d.ts +49 -0
  228. package/dist/render/shaders/gi/probeVolume.wgsl.js +242 -0
  229. package/dist/render/shaders/gi/sampleField.wgsl.d.ts +32 -0
  230. package/dist/render/shaders/gi/sampleField.wgsl.js +134 -0
  231. package/dist/render/shaders/gpudriven/blendRaster.wgsl.d.ts +26 -0
  232. package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +339 -0
  233. package/dist/render/shaders/gpudriven/compact.wgsl.d.ts +29 -0
  234. package/dist/render/shaders/gpudriven/compact.wgsl.js +58 -0
  235. package/dist/render/shaders/gpudriven/cull.wgsl.d.ts +90 -0
  236. package/dist/render/shaders/gpudriven/cull.wgsl.js +423 -0
  237. package/dist/render/shaders/gpudriven/decode.wgsl.d.ts +72 -0
  238. package/dist/render/shaders/gpudriven/decode.wgsl.js +349 -0
  239. package/dist/render/shaders/gpudriven/environment.wgsl.d.ts +44 -0
  240. package/dist/render/shaders/gpudriven/environment.wgsl.js +137 -0
  241. package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +28 -0
  242. package/dist/render/shaders/gpudriven/fog.wgsl.js +107 -0
  243. package/dist/render/shaders/gpudriven/frameBlock.wgsl.d.ts +13 -0
  244. package/dist/render/shaders/gpudriven/frameBlock.wgsl.js +62 -0
  245. package/dist/render/shaders/gpudriven/materialBin.wgsl.d.ts +51 -0
  246. package/dist/render/shaders/gpudriven/materialBin.wgsl.js +112 -0
  247. package/dist/render/shaders/gpudriven/materialTable.wgsl.d.ts +25 -0
  248. package/dist/render/shaders/gpudriven/materialTable.wgsl.js +43 -0
  249. package/dist/render/shaders/gpudriven/meshTransform.wgsl.d.ts +18 -0
  250. package/dist/render/shaders/gpudriven/meshTransform.wgsl.js +37 -0
  251. package/dist/render/shaders/gpudriven/present.wgsl.d.ts +43 -0
  252. package/dist/render/shaders/gpudriven/present.wgsl.js +127 -0
  253. package/dist/render/shaders/gpudriven/shade.wgsl.d.ts +127 -0
  254. package/dist/render/shaders/gpudriven/shade.wgsl.js +874 -0
  255. package/dist/render/shaders/gpudriven/shadow.wgsl.d.ts +44 -0
  256. package/dist/render/shaders/gpudriven/shadow.wgsl.js +308 -0
  257. package/dist/render/shaders/gpudriven/visbufferRaster.wgsl.d.ts +28 -0
  258. package/dist/render/shaders/gpudriven/visbufferRaster.wgsl.js +245 -0
  259. package/dist/render/shaders/network.wgsl.d.ts +101 -0
  260. package/dist/render/shaders/network.wgsl.js +206 -0
  261. package/dist/render/shaders/recon/motion.wgsl.d.ts +44 -0
  262. package/dist/render/shaders/recon/motion.wgsl.js +96 -0
  263. package/dist/render/shaders/recon/resolve.wgsl.d.ts +51 -0
  264. package/dist/render/shaders/recon/resolve.wgsl.js +733 -0
  265. package/dist/render/temporalAa.js +8 -33
  266. package/dist/render/textLayout.js +12 -6
  267. package/dist/render/textRenderer.d.ts +3 -1
  268. package/dist/render/textRenderer.js +4 -1
  269. package/dist/render/translucentQueue.d.ts +6 -0
  270. package/dist/render/translucentQueue.js +11 -0
  271. package/dist/render/windStreakRenderer.d.ts +2 -1
  272. package/dist/render/windStreakRenderer.js +3 -1
  273. package/dist/world/cell.d.ts +63 -0
  274. package/dist/world/cell.js +181 -0
  275. package/dist/world/cellStream.d.ts +103 -0
  276. package/dist/world/cellStream.js +198 -0
  277. package/dist/world/freeze.d.ts +81 -0
  278. package/dist/world/freeze.js +114 -0
  279. package/dist/world/rebase.d.ts +29 -0
  280. package/dist/world/rebase.js +41 -0
  281. package/package.json +8 -3
  282. package/scripts/frames.mjs +92 -0
  283. package/scripts/gpuCompute.mjs +323 -0
  284. package/scripts/png.d.mts +16 -0
  285. package/scripts/png.mjs +25 -0
  286. package/src/core/loop.ts +19 -2
  287. package/src/core/storage.ts +5 -0
  288. package/src/geometry/meshBuilder.ts +5 -1
  289. package/src/index.ts +261 -4
  290. package/src/input/input.ts +6 -1
  291. package/src/math/exact.ts +69 -3
  292. package/src/math/frustum.ts +52 -3
  293. package/src/render/backend/api.ts +42 -1
  294. package/src/render/backend/budget.ts +7 -6
  295. package/src/render/backend/createRenderer.ts +92 -3
  296. package/src/render/backend/materialChanges.ts +54 -0
  297. package/src/render/backend/select.ts +8 -0
  298. package/src/render/backend/webgl2/renderer.ts +211 -9
  299. package/src/render/backend/webgpu/buffers.ts +182 -69
  300. package/src/render/backend/webgpu/fieldCompose.ts +482 -0
  301. package/src/render/backend/webgpu/giFieldPass.ts +200 -0
  302. package/src/render/backend/webgpu/gpuDrivenPass.ts +2993 -0
  303. package/src/render/backend/webgpu/linePass.ts +4 -39
  304. package/src/render/backend/webgpu/probeBake.ts +588 -0
  305. package/src/render/backend/webgpu/renderer.ts +1481 -76
  306. package/src/render/backend/webgpu/scatterPass.ts +15 -1
  307. package/src/render/backend/webgpu/surfaceTexturePass.ts +158 -88
  308. package/src/render/causticsRenderer.ts +5 -2
  309. package/src/render/depthConvention.ts +15 -0
  310. package/src/render/deviceFeatures.ts +77 -0
  311. package/src/render/fog.ts +185 -0
  312. package/src/render/frame/alias.ts +97 -0
  313. package/src/render/frame/deps.ts +155 -0
  314. package/src/render/frame/flushGraph.ts +135 -0
  315. package/src/render/frame/graphSchedule.ts +170 -0
  316. package/src/render/frame/index.ts +52 -0
  317. package/src/render/frame/lifetime.ts +61 -0
  318. package/src/render/frame/passTimings.ts +69 -0
  319. package/src/render/frame/validate.ts +40 -0
  320. package/src/render/frame/virtual.ts +91 -0
  321. package/src/render/gi/chain.ts +225 -0
  322. package/src/render/gi/denoise.ts +276 -0
  323. package/src/render/gi/fieldScene.ts +264 -0
  324. package/src/render/gi/globalField.ts +543 -0
  325. package/src/render/gi/probeGridFit.ts +89 -0
  326. package/src/render/gi/probeTrace.ts +143 -0
  327. package/src/render/gi/probeVolume.ts +288 -0
  328. package/src/render/gi/reflection.ts +163 -0
  329. package/src/render/gi/traceField.ts +223 -0
  330. package/src/render/gi/traceScreen.ts +106 -0
  331. package/src/render/gpuScene.ts +80 -0
  332. package/src/render/gpudriven/alphaTest.ts +33 -0
  333. package/src/render/gpudriven/clusterUpload.ts +123 -0
  334. package/src/render/gpudriven/clusterWorld.ts +239 -0
  335. package/src/render/gpudriven/compact.ts +80 -0
  336. package/src/render/gpudriven/cullClusters.ts +333 -0
  337. package/src/render/gpudriven/decodeTables.ts +332 -0
  338. package/src/render/gpudriven/frustum.ts +70 -0
  339. package/src/render/gpudriven/geometryHarness.ts +51 -0
  340. package/src/render/gpudriven/hzb.ts +113 -0
  341. package/src/render/gpudriven/ibl.ts +147 -0
  342. package/src/render/gpudriven/indirect.ts +89 -0
  343. package/src/render/gpudriven/instances.ts +234 -0
  344. package/src/render/gpudriven/lit.ts +329 -0
  345. package/src/render/gpudriven/lodCut.ts +62 -0
  346. package/src/render/gpudriven/materialBin.ts +131 -0
  347. package/src/render/gpudriven/materialTable.ts +164 -0
  348. package/src/render/gpudriven/pipeline.ts +336 -0
  349. package/src/render/gpudriven/rangeAlloc.ts +122 -0
  350. package/src/render/gpudriven/sceneUpload.ts +173 -0
  351. package/src/render/gpudriven/shadeBins.ts +222 -0
  352. package/src/render/gpudriven/shadow.ts +285 -0
  353. package/src/render/gpudriven/shadowCamera.ts +406 -0
  354. package/src/render/gpudriven/streamScene.ts +575 -0
  355. package/src/render/gpudriven/surfaceFrame.ts +68 -0
  356. package/src/render/gpudriven/twoPhase.ts +214 -0
  357. package/src/render/gpudriven/visbuffer.ts +41 -0
  358. package/src/render/halfFloat.ts +22 -4
  359. package/src/render/inference/attentionTiled.ts +132 -0
  360. package/src/render/inference/denseKernels.ts +369 -0
  361. package/src/render/inference/device.ts +44 -0
  362. package/src/render/inference/deviceGraph.ts +39 -0
  363. package/src/render/inference/fuse.ts +47 -0
  364. package/src/render/inference/kernelKit.ts +120 -0
  365. package/src/render/inference/kernels.ts +18 -0
  366. package/src/render/inference/plan.ts +26 -0
  367. package/src/render/inference/reuse.ts +79 -0
  368. package/src/render/inference/runner.ts +204 -0
  369. package/src/render/inference/schedule.ts +80 -0
  370. package/src/render/inference/shapeKernels.ts +112 -0
  371. package/src/render/inference/spatialKernels.ts +220 -0
  372. package/src/render/inference/splatRaster.wgsl.ts +348 -0
  373. package/src/render/inference/splatTiles.ts +186 -0
  374. package/src/render/lineBatch.ts +4 -24
  375. package/src/render/mesh.ts +46 -1
  376. package/src/render/pass.ts +155 -10
  377. package/src/render/prefilterEnvMap.ts +33 -0
  378. package/src/render/readback.ts +73 -0
  379. package/src/render/recon/clamp.ts +113 -0
  380. package/src/render/recon/disocclusion.ts +143 -0
  381. package/src/render/recon/frameGen.ts +191 -0
  382. package/src/render/recon/frameSizes.ts +64 -0
  383. package/src/render/recon/jitter.ts +126 -0
  384. package/src/render/recon/motionVectors.ts +138 -0
  385. package/src/render/recon/reproject.ts +179 -0
  386. package/src/render/recon/resolve.ts +444 -0
  387. package/src/render/recon/tier.ts +31 -0
  388. package/src/render/reflectionProbe.ts +34 -0
  389. package/src/render/renderQuality.ts +87 -0
  390. package/src/render/screenSpaceReflection.ts +37 -3
  391. package/src/render/sdfFont.ts +2 -0
  392. package/src/render/segmentQuads.ts +39 -0
  393. package/src/render/shaders/flat/lobes.ts +35 -3
  394. package/src/render/shaders/flat/preamble.ts +25 -1
  395. package/src/render/shaders/flat/probeGrid.ts +77 -2
  396. package/src/render/shaders/generated/flat.wgsl.ts +64 -24
  397. package/src/render/shaders/gi/composeField.wgsl.ts +239 -0
  398. package/src/render/shaders/gi/marchField.wgsl.ts +146 -0
  399. package/src/render/shaders/gi/probeBake.wgsl.ts +649 -0
  400. package/src/render/shaders/gi/probeTrace.wgsl.ts +269 -0
  401. package/src/render/shaders/gi/probeVolume.wgsl.ts +246 -0
  402. package/src/render/shaders/gi/sampleField.wgsl.ts +140 -0
  403. package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +343 -0
  404. package/src/render/shaders/gpudriven/compact.wgsl.ts +59 -0
  405. package/src/render/shaders/gpudriven/cull.wgsl.ts +433 -0
  406. package/src/render/shaders/gpudriven/decode.wgsl.ts +373 -0
  407. package/src/render/shaders/gpudriven/environment.wgsl.ts +141 -0
  408. package/src/render/shaders/gpudriven/fog.wgsl.ts +110 -0
  409. package/src/render/shaders/gpudriven/frameBlock.wgsl.ts +62 -0
  410. package/src/render/shaders/gpudriven/materialBin.wgsl.ts +116 -0
  411. package/src/render/shaders/gpudriven/materialTable.wgsl.ts +46 -0
  412. package/src/render/shaders/gpudriven/meshTransform.wgsl.ts +37 -0
  413. package/src/render/shaders/gpudriven/present.wgsl.ts +129 -0
  414. package/src/render/shaders/gpudriven/shade.wgsl.ts +884 -0
  415. package/src/render/shaders/gpudriven/shadow.wgsl.ts +322 -0
  416. package/src/render/shaders/gpudriven/visbufferRaster.wgsl.ts +251 -0
  417. package/src/render/shaders/network.wgsl.ts +238 -0
  418. package/src/render/shaders/recon/motion.wgsl.ts +101 -0
  419. package/src/render/shaders/recon/resolve.wgsl.ts +741 -0
  420. package/src/render/temporalAa.ts +9 -33
  421. package/src/render/textLayout.ts +12 -6
  422. package/src/render/textRenderer.ts +5 -2
  423. package/src/render/translucentQueue.ts +11 -0
  424. package/src/render/windStreakRenderer.ts +4 -2
  425. package/src/world/cell.ts +231 -0
  426. package/src/world/cellStream.ts +278 -0
  427. package/src/world/freeze.ts +157 -0
  428. package/src/world/rebase.ts +56 -0
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Occlusion tested against depth from **this** frame rather than the last one.
3
+ *
4
+ * A hierarchical depth buffer is only an occluder if something has already been drawn into it, and
5
+ * the cheap way to have one at the start of a frame is to keep last frame's. That is wrong exactly
6
+ * when the camera moved: the pyramid describes a view nobody is looking from, and geometry the old
7
+ * view happened to hide is culled out of the new one. What it looks like is a wall or a floor
8
+ * disappearing for a frame or two after a cut, a teleport, or a fast turn — and it is intermittent,
9
+ * so it is reported as a streaming fault.
10
+ *
11
+ * **So the frame is drawn in two halves.** Phase one draws only what was visible last frame, which
12
+ * on a continuous camera is nearly everything and is a good occluder for the rest. The pyramid is
13
+ * reduced from *that* depth. Phase two then tests everything else against it and draws whatever
14
+ * phase one missed. Both halves write the same colour and depth, because they are one frame.
15
+ *
16
+ * **The history decides which phase a cluster is judged in and never whether it is judged.** Every
17
+ * cluster is in exactly one of the two lists, whatever the history holds, so a history that is
18
+ * stale — which after a teleport is all of it — costs a phase-two test and never a hole. That
19
+ * invariant is what makes the history safe to keep across a cut, and it is the one this file's
20
+ * tests assert most directly.
21
+ *
22
+ * **One history per view.** A shadow pass and the main camera see different things, and sharing a
23
+ * bit set between them puts one view's visibility into the other's phase one — which is the same
24
+ * defect as a stale history, arriving every frame instead of after a cut.
25
+ *
26
+ * The pass recording here is the frame graph's data rather than device calls: `phaseOnePasses` and
27
+ * `phaseTwoPasses` record what each half reads and writes, and the edge from the reduction's write
28
+ * to phase two's read *is* the guarantee in the first paragraph. Wiring them to a real encoder is
29
+ * Task 14's, against a consumer, for the reason `ARCHITECTURE.md` §3 gives about rendering changes
30
+ * nobody has looked at.
31
+ */
32
+
33
+ import { recordDeps } from '../frame/deps.ts';
34
+ import type { Deps } from '../frame/deps.ts';
35
+
36
+ /** Which clusters a view drew last frame, one bit each. */
37
+ export interface VisibilityHistory {
38
+ /** Thirty-two clusters a word, cluster `n` at bit `n & 31` of word `n >> 5`. */
39
+ bits: Uint32Array;
40
+ /** How many clusters it has room for. A wider one is allocated rather than the old one read. */
41
+ capacity: number;
42
+ }
43
+
44
+ export function createVisibilityHistory(capacity: number): VisibilityHistory {
45
+ return { bits: new Uint32Array(Math.max(1, Math.ceil(capacity / 32))), capacity };
46
+ }
47
+
48
+ /**
49
+ * Whether a cluster was drawn last frame.
50
+ *
51
+ * **Out of range answers false rather than throwing or wrapping.** A cluster index past the end is
52
+ * a scene that grew since the history was made, and the honest answer for one nobody has seen is
53
+ * "not last frame" — which puts it in phase two, where it is tested rather than assumed. Wrapping
54
+ * would put an unrelated cluster's bit in its place, which is a visibility answer for the wrong
55
+ * geometry and is invisible until it is wrong.
56
+ *
57
+ * **A perturbation survives this check and it is kept anyway.** `setHistory` refuses the same
58
+ * range, so no bit above `capacity` can ever be set, and a read past the end of the word array is
59
+ * `undefined` — which `&` coerces to zero and therefore answers false already. What it decides is
60
+ * the case where the two guards disagree, and the reason both are here rather than one is that
61
+ * they are read independently: the write side is the one a test can catch, and it is caught. The
62
+ * bits between `capacity` and the end of the last word are the ones that make the write side
63
+ * matter — forty clusters is two words, so twenty-four of them belong to nobody.
64
+ */
65
+ export function historyHas(history: VisibilityHistory, cluster: number): boolean {
66
+ if (cluster < 0 || cluster >= history.capacity) return false;
67
+ return ((history.bits[cluster >> 5] as number) & (1 << (cluster & 31))) !== 0;
68
+ }
69
+
70
+ export function setHistory(history: VisibilityHistory, cluster: number, drawn: boolean): void {
71
+ if (cluster < 0 || cluster >= history.capacity) return;
72
+ const word = cluster >> 5;
73
+ const mask = 1 << (cluster & 31);
74
+ const held = history.bits[word] as number;
75
+ history.bits[word] = drawn ? held | mask : held & ~mask;
76
+ }
77
+
78
+ export function clearHistory(history: VisibilityHistory): void {
79
+ history.bits.fill(0);
80
+ }
81
+
82
+ /** How many of the first `count` clusters the history holds. */
83
+ export function historyCount(history: VisibilityHistory, count: number): number {
84
+ let total = 0;
85
+ for (let cluster = 0; cluster < count; cluster += 1) if (historyHas(history, cluster)) total += 1;
86
+ return total;
87
+ }
88
+
89
+ /** The clusters phase one draws: exactly what was visible last frame, in index order. */
90
+ export function phaseOneClusters(
91
+ history: VisibilityHistory,
92
+ count: number,
93
+ out: Uint32Array,
94
+ ): number {
95
+ let at = 0;
96
+ for (let cluster = 0; cluster < count; cluster += 1) {
97
+ if (!historyHas(history, cluster)) continue;
98
+ out[at] = cluster;
99
+ at += 1;
100
+ }
101
+ return at;
102
+ }
103
+
104
+ /** The clusters phase two tests: everything the history does not hold. */
105
+ export function phaseTwoClusters(
106
+ history: VisibilityHistory,
107
+ count: number,
108
+ out: Uint32Array,
109
+ ): number {
110
+ let at = 0;
111
+ for (let cluster = 0; cluster < count; cluster += 1) {
112
+ if (historyHas(history, cluster)) continue;
113
+ out[at] = cluster;
114
+ at += 1;
115
+ }
116
+ return at;
117
+ }
118
+
119
+ /**
120
+ * Replace the history with what this frame actually drew.
121
+ *
122
+ * **Replace rather than accumulate**, and that is the half that is easy to leave out: a cluster
123
+ * kept in phase one and then culled in phase two has to leave the set, or it is drawn every frame
124
+ * for ever on the strength of having once been visible. `keep` is the flag buffer
125
+ * `cullClusters` writes, so this is one pass over the same array the draw used.
126
+ */
127
+ export function updateHistory(history: VisibilityHistory, keep: Uint32Array, count: number): void {
128
+ for (let cluster = 0; cluster < count; cluster += 1) {
129
+ setHistory(history, cluster, (keep[cluster] ?? 0) !== 0);
130
+ }
131
+ }
132
+
133
+ /** Every view's history, keyed by whatever identifier the caller gives its views. */
134
+ export interface VisibilityHistories {
135
+ readonly byView: Map<number, VisibilityHistory>;
136
+ }
137
+
138
+ export function createVisibilityHistories(): VisibilityHistories {
139
+ return { byView: new Map() };
140
+ }
141
+
142
+ /**
143
+ * This view's history, widened in place if the scene grew.
144
+ *
145
+ * **Widened rather than replaced**, because replacing it throws away a frame of visibility every
146
+ * time a cluster is added and puts the whole scene through phase two — which is correct and is
147
+ * also the slow path this feature exists to avoid.
148
+ */
149
+ export function historyFor(
150
+ store: VisibilityHistories,
151
+ view: number,
152
+ capacity: number,
153
+ ): VisibilityHistory {
154
+ const held = store.byView.get(view);
155
+ if (held === undefined) {
156
+ const made = createVisibilityHistory(capacity);
157
+ store.byView.set(view, made);
158
+ return made;
159
+ }
160
+ if (capacity > held.capacity) {
161
+ const widened = new Uint32Array(Math.max(1, Math.ceil(capacity / 32)));
162
+ widened.set(held.bits);
163
+ held.bits = widened;
164
+ held.capacity = capacity;
165
+ }
166
+ return held;
167
+ }
168
+
169
+ /** The virtual resources a two-phase frame moves between its halves. */
170
+ export interface TwoPhaseResources {
171
+ readonly colour: number;
172
+ readonly depth: number;
173
+ readonly hzb: number;
174
+ readonly clusters: number;
175
+ readonly keep: number;
176
+ }
177
+
178
+ /** Where phase one's two nodes landed in the dependency table. */
179
+ export interface PhaseOneNodes {
180
+ readonly draw: number;
181
+ readonly reduce: number;
182
+ }
183
+
184
+ /** Where phase two's two nodes landed. */
185
+ export interface PhaseTwoNodes {
186
+ readonly cull: number;
187
+ readonly draw: number;
188
+ }
189
+
190
+ /**
191
+ * Phase one: draw what was visible, then reduce the depth it produced into the pyramid.
192
+ *
193
+ * The reduction reads the depth the draw wrote, so nothing can reorder them and nothing can alias
194
+ * the depth away between them — which is exactly what `lifetime.ts` and `alias.ts` are reading
195
+ * these edges for.
196
+ */
197
+ export function phaseOnePasses(deps: Deps, res: TwoPhaseResources): PhaseOneNodes {
198
+ const draw = recordDeps(deps, [res.clusters], [res.colour, res.depth]);
199
+ const reduce = recordDeps(deps, [res.depth], [res.hzb]);
200
+ return { draw, reduce };
201
+ }
202
+
203
+ /**
204
+ * Phase two: cull everything else against that pyramid, then draw what survived.
205
+ *
206
+ * `cull` reads `hzb`, which `phaseOnePasses` wrote. That one edge is the whole claim of this
207
+ * module — the depth being tested against belongs to this frame — expressed where the scheduler
208
+ * can enforce it rather than in a comment somebody has to obey.
209
+ */
210
+ export function phaseTwoPasses(deps: Deps, res: TwoPhaseResources): PhaseTwoNodes {
211
+ const cull = recordDeps(deps, [res.hzb, res.clusters], [res.keep]);
212
+ const draw = recordDeps(deps, [res.keep, res.clusters], [res.colour, res.depth]);
213
+ return { cull, draw };
214
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * What a pixel records: which triangle of which cluster of which instance covered it.
3
+ *
4
+ * **One 32-bit target, and its ceiling is stated here rather than discovered.** Seven bits carry
5
+ * the triangle, which is the 128 a cluster may hold, and the remaining twenty-five carry the
6
+ * cluster-in-instance identifier — 33.5 million of them, far past what a streaming budget permits.
7
+ * If a scene ever reaches it the answer is a second target, not a repack.
8
+ *
9
+ * **Zero is a legal value, so the buffer is cleared to a sentinel instead.** Cleared to zero, an
10
+ * uncovered pixel is indistinguishable from triangle 0 of cluster 0 of instance 0, which is a real
11
+ * triangle in every scene that has one.
12
+ */
13
+
14
+ /** Triangles a cluster may hold, and therefore what the low bits carry. */
15
+ export const VIS_TRIANGLE_BITS = 7;
16
+ export const VIS_MAX_TRIANGLES = 1 << VIS_TRIANGLE_BITS;
17
+ /** Cluster-in-instance identifiers the remaining bits carry. */
18
+ export const VIS_MAX_CLUSTERS = 1 << (32 - VIS_TRIANGLE_BITS);
19
+ /** What an uncovered pixel holds. Not zero — see the header. */
20
+ export const VIS_EMPTY = 0xffffffff;
21
+
22
+ export function packVisibility(cluster: number, triangle: number): number {
23
+ if (triangle < 0 || triangle >= VIS_MAX_TRIANGLES) {
24
+ throw new RangeError(`triangle ${triangle} does not fit in ${VIS_TRIANGLE_BITS} bits`);
25
+ }
26
+ if (cluster < 0 || cluster >= VIS_MAX_CLUSTERS) {
27
+ throw new RangeError(`cluster ${cluster} does not fit in ${32 - VIS_TRIANGLE_BITS} bits`);
28
+ }
29
+ return ((cluster << VIS_TRIANGLE_BITS) | triangle) >>> 0;
30
+ }
31
+
32
+ export function unpackVisibility(packed: number): { cluster: number; triangle: number } {
33
+ return {
34
+ cluster: packed >>> VIS_TRIANGLE_BITS,
35
+ triangle: packed & (VIS_MAX_TRIANGLES - 1),
36
+ };
37
+ }
38
+
39
+ export function visibilityCovered(packed: number): boolean {
40
+ return packed !== VIS_EMPTY;
41
+ }
@@ -5,6 +5,16 @@ const conversion = new ArrayBuffer(4);
5
5
  const asFloat = new Float32Array(conversion);
6
6
  const asUint = new Uint32Array(conversion);
7
7
 
8
+ /**
9
+ * The nearest half to `value`, ties to even — IEEE 754's default, and what the network runner's
10
+ * half-precision weights need, since the reference they are checked against rounds the same way.
11
+ *
12
+ * **This truncated until 2026-09-19**, so every value moved toward zero by up to a whole unit in the
13
+ * last place: an environment cube lost radiance on every texel rather than rounding on each, and a
14
+ * weight disagreed with the reference's by as much. Rounding costs a few operations per value and
15
+ * runs once per upload. The carry a round produces is added into the packed bits, so a mantissa that
16
+ * overflows lifts the exponent — and past 65,504 lands on infinity — with no case of its own.
17
+ */
8
18
  export function halfBits(value: number): number {
9
19
  asFloat[0] = value;
10
20
  const bits = asUint[0] ?? 0;
@@ -18,17 +28,25 @@ export function halfBits(value: number): number {
18
28
  /* Rebias 127 to 15. Above half's range saturates to infinity rather than wrapping to zero. */
19
29
  exponent = exponent - 127 + 15;
20
30
  if (exponent >= 0x1f) return sign | 0x7c00;
31
+ let shift = 13;
32
+ let packed: number;
21
33
  if (exponent <= 0) {
22
34
  /*
23
35
  * Subnormal. An environment's darkest texels live here, and flushing them to zero is what
24
- * makes a night sky's gradient band — so they are shifted rather than discarded.
36
+ * makes a night sky's gradient band — so they are shifted rather than discarded. Below half the
37
+ * smallest subnormal, nothing is left to round up.
25
38
  */
26
39
  if (exponent < -10) return sign;
27
40
  mantissa |= 0x800000;
28
- const shift = 14 - exponent;
29
- return sign | (mantissa >>> shift);
41
+ shift = 14 - exponent;
42
+ packed = mantissa >>> shift;
43
+ } else {
44
+ packed = (exponent << 10) | (mantissa >>> 13);
30
45
  }
31
- return sign | (exponent << 10) | (mantissa >>> 13);
46
+ const halfway = 1 << (shift - 1);
47
+ const rest = mantissa & ((1 << shift) - 1);
48
+ const up = rest > halfway || (rest === halfway && (packed & 1) === 1);
49
+ return sign | (packed + (up ? 1 : 0));
32
50
  }
33
51
 
34
52
  /** A whole array of floats as binary16, which is what a `r16float` or `rgba16float` upload wants. */
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Attention with keys and values staged in workgroup memory: many queries against many keys, at
3
+ * head widths that would spill an invocation's accumulator from its registers.
4
+ *
5
+ * **A workgroup takes one window's head and as many of its queries as 256 threads hold**, each
6
+ * thread one query and 16 of the head's channels — so what a thread keeps is 16 values of its output
7
+ * and as many of its query, where the other two forms keep the whole head; a head of 256 is 16
8
+ * queries a workgroup, and a head of 64 is 64, and every key staged serves each of them. Keys come
9
+ * in tiles of 8: the tile is staged, each thread's share of every query-key dot is written out, a
10
+ * dot's shares are summed, and the same memory then holds the tile's values for the weighted sum. A
11
+ * query's softmax runs key by key with the running maximum, exactly as the other forms run it, so
12
+ * the bound that holds for them holds here.
13
+ *
14
+ * **What it gives up is barriers**: four a tile, so 2,000 for 4,096 keys, which is why it is chosen
15
+ * where the work is large enough to pay for them. The memory is under 16 KB at any width — at a
16
+ * head of 256, all of what a workgroup is promised — and a head wider than that, or one sixteen does
17
+ * not divide, takes one of the other forms.
18
+ */
19
+ import {
20
+ type KernelRequest,
21
+ type KernelSource,
22
+ float,
23
+ header,
24
+ num,
25
+ perRow,
26
+ read,
27
+ } from './kernelKit.ts';
28
+
29
+ const THREADS = 256;
30
+ const KEYS = 8;
31
+
32
+ /*
33
+ * The groups a query's channels split into: 8, or 16 above a head of 128, which measured best on an
34
+ * RX 9070 XT — 8 took a head of 64 from 1.37 ms at 16 to 1.0 and a head of 96 from 7.3 to 4.8, and
35
+ * 16 took a head of 256 from 22.4 at 8 to 12.2 (`tools/capture-weights/opbudget.ts`).
36
+ */
37
+ export function tiledGroups(d: number): number {
38
+ return d > 128 ? 16 : 8;
39
+ }
40
+
41
+ /** Whether this form can take a head of `d` channels in `groups` groups. */
42
+ export function tiledAttentionFits(d: number, groups = tiledGroups(d)): boolean {
43
+ return d % groups === 0 && d <= 256;
44
+ }
45
+
46
+ /**
47
+ * The tiled form, each query's channels in `groups` groups and so `256 / groups` queries a
48
+ * workgroup. `attentionKernel` chooses it; the argument is how `opbudget.ts` measured the choice.
49
+ */
50
+ export function tiledAttention(request: KernelRequest, groups?: number): KernelSource {
51
+ const queryShape = request.inputShapes[0] as readonly number[];
52
+ const [queries, channels] = queryShape.slice(-2) as [number, number];
53
+ const keys = (request.inputShapes[1] as readonly number[]).at(-2) as number;
54
+ const batch = queryShape.length === 3 ? (queryShape[0] as number) : 1;
55
+ const heads = num(request.attributes, 'heads', 1);
56
+ const d = channels / heads;
57
+ const GROUPS = groups ?? tiledGroups(d);
58
+ const share = d / GROUPS;
59
+ const QUERIES = THREADS / GROUPS;
60
+ const threads = THREADS;
61
+ const blocks = Math.ceil(queries / QUERIES);
62
+ const grid = perRow(batch * heads * blocks);
63
+ const bias =
64
+ request.inputShapes.length > 3
65
+ ? ` + ${read(request, 3, `(head * ${queries}u + min(query, ${queries - 1}u)) * ${keys}u + key`)}`
66
+ : '';
67
+ const stage = (
68
+ input: number,
69
+ ): string => ` for (var i = local.x; i < ${KEYS * d}u; i = i + ${threads}u) {
70
+ let key = start + i / ${d}u;
71
+ tile[i] = select(0.0, ${read(request, input, `(keyRow + min(key, ${keys - 1}u)) * ${channels}u + first + i % ${d}u`)}, key < ${keys}u);
72
+ }
73
+ workgroupBarrier();`;
74
+ return {
75
+ code: `${header(request)}
76
+
77
+ var<workgroup> tile: array<f32, ${KEYS * d}>;
78
+ var<workgroup> partial: array<f32, ${QUERIES * KEYS * GROUPS}>;
79
+
80
+ @compute @workgroup_size(${threads})
81
+ fn main(@builtin(workgroup_id) group: vec3<u32>, @builtin(local_invocation_id) local: vec3<u32>) {
82
+ let block = ${grid.row};
83
+ if (block >= ${batch * heads * blocks}u) { return; }
84
+ let window = block / ${heads * blocks}u;
85
+ let head = (block / ${blocks}u) % ${heads}u;
86
+ let r = local.x / ${GROUPS}u;
87
+ let g = local.x % ${GROUPS}u;
88
+ let query = (block % ${blocks}u) * ${QUERIES}u + r;
89
+ let row = window * ${queries}u + min(query, ${queries - 1}u);
90
+ let keyRow = window * ${keys}u;
91
+ let first = head * ${d}u;
92
+ let own = g * ${share}u;
93
+ var mine: array<f32, ${share}>;
94
+ var gathered: array<f32, ${share}>;
95
+ for (var c = 0u; c < ${share}u; c = c + 1u) { mine[c] = ${read(request, 0, `row * ${channels}u + first + own + c`)}; }
96
+ var largest = -3.4028234e38;
97
+ var total = 0.0;
98
+ for (var start = 0u; start < ${keys}u; start = start + ${KEYS}u) {
99
+ ${stage(1)}
100
+ for (var k = 0u; k < ${KEYS}u; k = k + 1u) {
101
+ var dot = 0.0;
102
+ for (var c = 0u; c < ${share}u; c = c + 1u) { dot = dot + mine[c] * tile[k * ${d}u + own + c]; }
103
+ partial[(r * ${KEYS}u + k) * ${GROUPS}u + g] = dot;
104
+ }
105
+ workgroupBarrier();
106
+ for (var k = g; k < ${KEYS}u; k = k + ${GROUPS}u) {
107
+ var sum = 0.0;
108
+ for (var j = 0u; j < ${GROUPS}u; j = j + 1u) { sum = sum + partial[(r * ${KEYS}u + k) * ${GROUPS}u + j]; }
109
+ partial[(r * ${KEYS}u + k) * ${GROUPS}u] = sum;
110
+ }
111
+ ${stage(2)}
112
+ for (var k = 0u; k < ${KEYS}u; k = k + 1u) {
113
+ let key = start + k;
114
+ if (key >= ${keys}u) { break; }
115
+ let score = partial[(r * ${KEYS}u + k) * ${GROUPS}u] * ${float(1 / Math.sqrt(d))}${bias};
116
+ let top = max(largest, score);
117
+ let rescale = exp(largest - top);
118
+ let weight = exp(score - top);
119
+ total = total * rescale + weight;
120
+ for (var c = 0u; c < ${share}u; c = c + 1u) { gathered[c] = gathered[c] * rescale + weight * tile[k * ${d}u + own + c]; }
121
+ largest = top;
122
+ }
123
+ workgroupBarrier();
124
+ }
125
+ if (query < ${queries}u) {
126
+ for (var c = 0u; c < ${share}u; c = c + 1u) { output[row * ${channels}u + first + own + c] = gathered[c] / total; }
127
+ }
128
+ }
129
+ `,
130
+ workgroups: grid.workgroups,
131
+ };
132
+ }