@drawcall/lod 0.1.2 → 0.3.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 (358) hide show
  1. package/README.md +13 -70
  2. package/dist/at.d.ts +2 -0
  3. package/dist/at.js +8 -0
  4. package/dist/at.js.map +1 -0
  5. package/dist/bake.d.ts +22 -0
  6. package/dist/bake.js +88 -0
  7. package/dist/bake.js.map +1 -0
  8. package/dist/baked/codec.d.ts +5 -5
  9. package/dist/baked/codec.js +58 -158
  10. package/dist/baked/codec.js.map +1 -1
  11. package/dist/baked/coverage.d.ts +6 -3
  12. package/dist/baked/coverage.js +6 -3
  13. package/dist/baked/coverage.js.map +1 -1
  14. package/dist/baked/fields.d.ts +9 -0
  15. package/dist/baked/fields.js +22 -0
  16. package/dist/baked/fields.js.map +1 -0
  17. package/dist/baked/index.d.ts +16 -6
  18. package/dist/baked/index.js +23 -21
  19. package/dist/baked/index.js.map +1 -1
  20. package/dist/baked/interior/faces.d.ts +4 -3
  21. package/dist/baked/interior/faces.js +13 -10
  22. package/dist/baked/interior/faces.js.map +1 -1
  23. package/dist/baked/interior/material.d.ts +7 -10
  24. package/dist/baked/interior/material.js +29 -36
  25. package/dist/baked/interior/material.js.map +1 -1
  26. package/dist/baked/interior/rooms.js +1 -1
  27. package/dist/baked/interior/rooms.js.map +1 -1
  28. package/dist/baked/low.d.ts +2 -2
  29. package/dist/baked/low.js +9 -8
  30. package/dist/baked/low.js.map +1 -1
  31. package/dist/baked/raster.js +6 -6
  32. package/dist/baked/raster.js.map +1 -1
  33. package/dist/baked/textures.d.ts +17 -0
  34. package/dist/baked/textures.js +95 -0
  35. package/dist/baked/textures.js.map +1 -0
  36. package/dist/baked/transfer.js +19 -18
  37. package/dist/baked/transfer.js.map +1 -1
  38. package/dist/baked/unwrap.js +4 -3
  39. package/dist/baked/unwrap.js.map +1 -1
  40. package/dist/baked/xatlas.js.map +1 -1
  41. package/dist/codec/container.d.ts +8 -0
  42. package/dist/codec/container.js +63 -0
  43. package/dist/codec/container.js.map +1 -0
  44. package/dist/codec/mesh.d.ts +8 -0
  45. package/dist/codec/mesh.js +220 -0
  46. package/dist/codec/mesh.js.map +1 -0
  47. package/dist/dispose.d.ts +11 -4
  48. package/dist/dispose.js +39 -12
  49. package/dist/dispose.js.map +1 -1
  50. package/dist/gpu.d.ts +39 -0
  51. package/dist/gpu.js +41 -0
  52. package/dist/gpu.js.map +1 -0
  53. package/dist/impostor/bake/atlas.d.ts +4 -4
  54. package/dist/impostor/bake/atlas.js +12 -12
  55. package/dist/impostor/bake/atlas.js.map +1 -1
  56. package/dist/impostor/bake/fit.d.ts +8 -0
  57. package/dist/impostor/bake/fit.js +28 -0
  58. package/dist/impostor/bake/fit.js.map +1 -0
  59. package/dist/impostor/bake/index.d.ts +23 -14
  60. package/dist/impostor/bake/index.js +42 -134
  61. package/dist/impostor/bake/index.js.map +1 -1
  62. package/dist/impostor/bake/materials.d.ts +3 -3
  63. package/dist/impostor/bake/materials.js +60 -12
  64. package/dist/impostor/bake/materials.js.map +1 -1
  65. package/dist/impostor/bake/sheet.d.ts +8 -0
  66. package/dist/impostor/bake/sheet.js +90 -0
  67. package/dist/impostor/bake/sheet.js.map +1 -0
  68. package/dist/impostor/bake/source.d.ts +2 -2
  69. package/dist/impostor/bake/source.js +8 -19
  70. package/dist/impostor/bake/source.js.map +1 -1
  71. package/dist/impostor/codec.d.ts +5 -11
  72. package/dist/impostor/codec.js +37 -121
  73. package/dist/impostor/codec.js.map +1 -1
  74. package/dist/impostor/impostor.d.ts +31 -7
  75. package/dist/impostor/impostor.js +21 -6
  76. package/dist/impostor/impostor.js.map +1 -1
  77. package/dist/impostor/ktx2/encode.d.ts +26 -0
  78. package/dist/impostor/ktx2/encode.js +117 -0
  79. package/dist/impostor/ktx2/encode.js.map +1 -0
  80. package/dist/impostor/ktx2/transcode.d.ts +3 -0
  81. package/dist/impostor/ktx2/transcode.js +99 -0
  82. package/dist/impostor/ktx2/transcode.js.map +1 -0
  83. package/dist/impostor/ktx2/uastc.d.ts +7 -0
  84. package/dist/impostor/ktx2/uastc.js +64 -0
  85. package/dist/impostor/ktx2/uastc.js.map +1 -0
  86. package/dist/impostor/ktx2/wasm/encoder.d.ts +4 -0
  87. package/dist/impostor/ktx2/wasm/encoder.js +10 -0
  88. package/dist/impostor/ktx2/wasm/encoder.js.map +1 -0
  89. package/dist/impostor/ktx2/wasm/transcoder.d.ts +3 -0
  90. package/dist/impostor/ktx2/wasm/transcoder.js +9 -0
  91. package/dist/impostor/ktx2/wasm/transcoder.js.map +1 -0
  92. package/dist/impostor/ktx2/worker.d.ts +1 -0
  93. package/dist/impostor/ktx2/worker.js +12 -0
  94. package/dist/impostor/ktx2/worker.js.map +1 -0
  95. package/dist/impostor/mesh/card.d.ts +3 -3
  96. package/dist/impostor/mesh/card.js +11 -8
  97. package/dist/impostor/mesh/card.js.map +1 -1
  98. package/dist/impostor/mesh/index.d.ts +10 -7
  99. package/dist/impostor/mesh/index.js +15 -18
  100. package/dist/impostor/mesh/index.js.map +1 -1
  101. package/dist/impostor/mesh/material.d.ts +24 -13
  102. package/dist/impostor/mesh/material.js +67 -51
  103. package/dist/impostor/mesh/material.js.map +1 -1
  104. package/dist/impostor/mesh/surface.d.ts +20 -16
  105. package/dist/impostor/mesh/surface.js +81 -58
  106. package/dist/impostor/mesh/surface.js.map +1 -1
  107. package/dist/impostor/mesh/textures.d.ts +3 -3
  108. package/dist/impostor/mesh/textures.js +24 -34
  109. package/dist/impostor/mesh/textures.js.map +1 -1
  110. package/dist/impostor/octahedral.d.ts +1 -8
  111. package/dist/impostor/octahedral.js +3 -18
  112. package/dist/impostor/octahedral.js.map +1 -1
  113. package/dist/index.d.ts +16 -10
  114. package/dist/index.js +14 -8
  115. package/dist/index.js.map +1 -1
  116. package/dist/instanced/camera.d.ts +46 -0
  117. package/dist/instanced/camera.js +70 -0
  118. package/dist/instanced/camera.js.map +1 -0
  119. package/dist/instanced/chunk.d.ts +97 -0
  120. package/dist/instanced/chunk.js +156 -0
  121. package/dist/instanced/chunk.js.map +1 -0
  122. package/dist/instanced/chunks.d.ts +60 -0
  123. package/dist/instanced/chunks.js +208 -0
  124. package/dist/instanced/chunks.js.map +1 -0
  125. package/dist/instanced/cull.d.ts +28 -0
  126. package/dist/instanced/cull.js +22 -0
  127. package/dist/instanced/cull.js.map +1 -0
  128. package/dist/instanced/index.d.ts +96 -92
  129. package/dist/instanced/index.js +229 -512
  130. package/dist/instanced/index.js.map +1 -1
  131. package/dist/instanced/key.d.ts +19 -0
  132. package/dist/instanced/key.js +45 -0
  133. package/dist/instanced/key.js.map +1 -0
  134. package/dist/instanced/levels.d.ts +60 -0
  135. package/dist/instanced/levels.js +130 -0
  136. package/dist/instanced/levels.js.map +1 -0
  137. package/dist/instanced/lists.d.ts +70 -0
  138. package/dist/instanced/lists.js +133 -0
  139. package/dist/instanced/lists.js.map +1 -0
  140. package/dist/instanced/measure.d.ts +28 -0
  141. package/dist/instanced/measure.js +203 -0
  142. package/dist/instanced/measure.js.map +1 -0
  143. package/dist/instanced/meshes.d.ts +46 -14
  144. package/dist/instanced/meshes.js +137 -22
  145. package/dist/instanced/meshes.js.map +1 -1
  146. package/dist/instanced/mirror.d.ts +20 -0
  147. package/dist/instanced/mirror.js +37 -0
  148. package/dist/instanced/mirror.js.map +1 -0
  149. package/dist/instanced/pages/buffers.d.ts +37 -0
  150. package/dist/instanced/pages/buffers.js +15 -0
  151. package/dist/instanced/pages/buffers.js.map +1 -0
  152. package/dist/instanced/pages/chunk.d.ts +51 -0
  153. package/dist/instanced/pages/chunk.js +81 -0
  154. package/dist/instanced/pages/chunk.js.map +1 -0
  155. package/dist/instanced/pages/index.d.ts +74 -0
  156. package/dist/instanced/pages/index.js +269 -0
  157. package/dist/instanced/pages/index.js.map +1 -0
  158. package/dist/instanced/pages/passes.d.ts +21 -0
  159. package/dist/instanced/pages/passes.js +52 -0
  160. package/dist/instanced/pages/passes.js.map +1 -0
  161. package/dist/instanced/pages/slots.d.ts +11 -0
  162. package/dist/instanced/pages/slots.js +90 -0
  163. package/dist/instanced/pages/slots.js.map +1 -0
  164. package/dist/instanced/pages/workgroup.d.ts +14 -0
  165. package/dist/instanced/pages/workgroup.js +38 -0
  166. package/dist/instanced/pages/workgroup.js.map +1 -0
  167. package/dist/instanced/raycast.d.ts +15 -0
  168. package/dist/instanced/raycast.js +46 -0
  169. package/dist/instanced/raycast.js.map +1 -0
  170. package/dist/instanced/rows.d.ts +108 -0
  171. package/dist/instanced/rows.js +209 -0
  172. package/dist/instanced/rows.js.map +1 -0
  173. package/dist/instanced/shape.d.ts +25 -0
  174. package/dist/instanced/shape.js +51 -0
  175. package/dist/instanced/shape.js.map +1 -0
  176. package/dist/instanced/sort.d.ts +63 -0
  177. package/dist/instanced/sort.js +162 -0
  178. package/dist/instanced/sort.js.map +1 -0
  179. package/dist/instanced/update.d.ts +30 -0
  180. package/dist/instanced/update.js +207 -0
  181. package/dist/instanced/update.js.map +1 -0
  182. package/dist/levels/bounds.d.ts +21 -0
  183. package/dist/levels/bounds.js +42 -0
  184. package/dist/levels/bounds.js.map +1 -0
  185. package/dist/levels/cameras.d.ts +48 -0
  186. package/dist/levels/cameras.js +122 -0
  187. package/dist/levels/cameras.js.map +1 -0
  188. package/dist/levels/compile/contexts.d.ts +30 -0
  189. package/dist/levels/compile/contexts.js +18 -0
  190. package/dist/levels/compile/contexts.js.map +1 -0
  191. package/dist/levels/compile/index.d.ts +39 -0
  192. package/dist/levels/compile/index.js +185 -0
  193. package/dist/levels/compile/index.js.map +1 -0
  194. package/dist/levels/compile/pipelines.d.ts +26 -0
  195. package/dist/levels/compile/pipelines.js +177 -0
  196. package/dist/levels/compile/pipelines.js.map +1 -0
  197. package/dist/levels/compiles.d.ts +29 -0
  198. package/dist/levels/compiles.js +50 -0
  199. package/dist/levels/compiles.js.map +1 -0
  200. package/dist/levels/draw.d.ts +102 -0
  201. package/dist/levels/draw.js +401 -0
  202. package/dist/levels/draw.js.map +1 -0
  203. package/dist/levels/fade.d.ts +69 -0
  204. package/dist/levels/fade.js +150 -0
  205. package/dist/levels/fade.js.map +1 -0
  206. package/dist/levels/index.d.ts +99 -0
  207. package/dist/levels/index.js +155 -0
  208. package/dist/levels/index.js.map +1 -0
  209. package/dist/levels/item.d.ts +38 -0
  210. package/dist/levels/item.js +97 -0
  211. package/dist/levels/item.js.map +1 -0
  212. package/dist/levels/load.d.ts +31 -0
  213. package/dist/levels/load.js +142 -0
  214. package/dist/levels/load.js.map +1 -0
  215. package/dist/levels/manager.d.ts +159 -0
  216. package/dist/levels/manager.js +339 -0
  217. package/dist/levels/manager.js.map +1 -0
  218. package/dist/{material.js → levels/material.js} +13 -7
  219. package/dist/levels/material.js.map +1 -0
  220. package/dist/levels/renderer.d.ts +29 -0
  221. package/dist/levels/renderer.js +41 -0
  222. package/dist/levels/renderer.js.map +1 -0
  223. package/dist/levels/requests.d.ts +49 -0
  224. package/dist/levels/requests.js +95 -0
  225. package/dist/levels/requests.js.map +1 -0
  226. package/dist/levels/screen.d.ts +14 -0
  227. package/dist/levels/screen.js +21 -0
  228. package/dist/levels/screen.js.map +1 -0
  229. package/dist/levels/wait.d.ts +27 -0
  230. package/dist/levels/wait.js +61 -0
  231. package/dist/levels/wait.js.map +1 -0
  232. package/dist/loader/build.d.ts +10 -0
  233. package/dist/loader/build.js +28 -0
  234. package/dist/loader/build.js.map +1 -0
  235. package/dist/loader/cache.d.ts +12 -15
  236. package/dist/loader/cache.js +64 -33
  237. package/dist/loader/cache.js.map +1 -1
  238. package/dist/loader/context.d.ts +46 -0
  239. package/dist/loader/context.js +91 -0
  240. package/dist/loader/context.js.map +1 -0
  241. package/dist/loader/dependencies.d.ts +32 -0
  242. package/dist/loader/dependencies.js +113 -0
  243. package/dist/loader/dependencies.js.map +1 -0
  244. package/dist/loader/index.d.ts +62 -0
  245. package/dist/loader/index.js +284 -0
  246. package/dist/loader/index.js.map +1 -0
  247. package/dist/loader/level.d.ts +41 -0
  248. package/dist/loader/level.js +140 -0
  249. package/dist/loader/level.js.map +1 -0
  250. package/dist/loader/request.d.ts +87 -0
  251. package/dist/loader/request.js +59 -0
  252. package/dist/loader/request.js.map +1 -0
  253. package/dist/loader/url.d.ts +16 -0
  254. package/dist/loader/url.js +35 -0
  255. package/dist/loader/url.js.map +1 -0
  256. package/dist/lod.d.ts +79 -49
  257. package/dist/lod.js +209 -153
  258. package/dist/lod.js.map +1 -1
  259. package/dist/meshopt.d.ts +6 -0
  260. package/dist/meshopt.js +19 -0
  261. package/dist/meshopt.js.map +1 -0
  262. package/dist/simplify/cards.d.ts +14 -0
  263. package/dist/simplify/cards.js +128 -0
  264. package/dist/simplify/cards.js.map +1 -0
  265. package/dist/{simplify.d.ts → simplify/index.d.ts} +7 -4
  266. package/dist/{simplify.js → simplify/index.js} +42 -22
  267. package/dist/simplify/index.js.map +1 -0
  268. package/dist/{bounds.d.ts → source/detail.d.ts} +4 -13
  269. package/dist/{bounds.js → source/detail.js} +62 -32
  270. package/dist/source/detail.js.map +1 -0
  271. package/dist/source/{error.d.ts → deviation.d.ts} +3 -3
  272. package/dist/source/{error.js → deviation.js} +12 -12
  273. package/dist/source/deviation.js.map +1 -0
  274. package/dist/source/{shading.d.ts → evaluator.d.ts} +10 -10
  275. package/dist/source/{shading.js → evaluator.js} +5 -5
  276. package/dist/source/evaluator.js.map +1 -0
  277. package/dist/source/{trace.d.ts → raycaster.d.ts} +6 -6
  278. package/dist/source/{trace.js → raycaster.js} +8 -8
  279. package/dist/source/raycaster.js.map +1 -0
  280. package/dist/source/{texels.d.ts → sampler.d.ts} +1 -1
  281. package/dist/source/{texels.js → sampler.js} +3 -3
  282. package/dist/source/sampler.js.map +1 -0
  283. package/dist/source/source.d.ts +2 -2
  284. package/dist/source/source.js +2 -2
  285. package/dist/source/source.js.map +1 -1
  286. package/dist/source/surface.js +1 -1
  287. package/dist/source/surface.js.map +1 -1
  288. package/dist/task.d.ts +6 -0
  289. package/dist/{pause.js → task.js} +5 -5
  290. package/dist/task.js.map +1 -0
  291. package/dist/three.d.ts +20 -19
  292. package/dist/three.js +29 -35
  293. package/dist/three.js.map +1 -1
  294. package/dist/tsl.d.ts +10 -14
  295. package/dist/tsl.js +12 -47
  296. package/dist/tsl.js.map +1 -1
  297. package/dist/typegpu.d.ts +37 -0
  298. package/dist/typegpu.js +37 -0
  299. package/dist/typegpu.js.map +1 -0
  300. package/dist/wind/bounds.js +2 -2
  301. package/dist/wind/bounds.js.map +1 -1
  302. package/dist/wind/hooks.d.ts +7 -4
  303. package/dist/wind/hooks.js +5 -2
  304. package/dist/wind/hooks.js.map +1 -1
  305. package/dist/wind/index.d.ts +4 -4
  306. package/dist/wind/index.js +43 -40
  307. package/dist/wind/index.js.map +1 -1
  308. package/dist/wind/sway.d.ts +4 -1
  309. package/dist/wind/sway.js +4 -1
  310. package/dist/wind/sway.js.map +1 -1
  311. package/package.json +24 -8
  312. package/skills/lod/SKILL.md +147 -108
  313. package/dist/bounds.js.map +0 -1
  314. package/dist/fade.d.ts +0 -44
  315. package/dist/fade.js +0 -78
  316. package/dist/fade.js.map +0 -1
  317. package/dist/impostor/cache.d.ts +0 -15
  318. package/dist/impostor/cache.js +0 -44
  319. package/dist/impostor/cache.js.map +0 -1
  320. package/dist/instanced/args.d.ts +0 -20
  321. package/dist/instanced/args.js +0 -77
  322. package/dist/instanced/args.js.map +0 -1
  323. package/dist/instanced/bounds.d.ts +0 -50
  324. package/dist/instanced/bounds.js +0 -271
  325. package/dist/instanced/bounds.js.map +0 -1
  326. package/dist/instanced/dirty.d.ts +0 -12
  327. package/dist/instanced/dirty.js +0 -61
  328. package/dist/instanced/dirty.js.map +0 -1
  329. package/dist/instanced/select.d.ts +0 -84
  330. package/dist/instanced/select.js +0 -264
  331. package/dist/instanced/select.js.map +0 -1
  332. package/dist/lazy.d.ts +0 -64
  333. package/dist/lazy.js +0 -187
  334. package/dist/lazy.js.map +0 -1
  335. package/dist/levels.d.ts +0 -72
  336. package/dist/levels.js +0 -146
  337. package/dist/levels.js.map +0 -1
  338. package/dist/loader/dispose.d.ts +0 -3
  339. package/dist/loader/dispose.js +0 -25
  340. package/dist/loader/dispose.js.map +0 -1
  341. package/dist/loader.d.ts +0 -99
  342. package/dist/loader.js +0 -234
  343. package/dist/loader.js.map +0 -1
  344. package/dist/material.js.map +0 -1
  345. package/dist/pause.d.ts +0 -6
  346. package/dist/pause.js.map +0 -1
  347. package/dist/renderer.d.ts +0 -21
  348. package/dist/renderer.js +0 -83
  349. package/dist/renderer.js.map +0 -1
  350. package/dist/simplify.js.map +0 -1
  351. package/dist/source/error.js.map +0 -1
  352. package/dist/source/shading.js.map +0 -1
  353. package/dist/source/texels.js.map +0 -1
  354. package/dist/source/trace.js.map +0 -1
  355. package/dist/view.d.ts +0 -30
  356. package/dist/view.js +0 -75
  357. package/dist/view.js.map +0 -1
  358. /package/dist/{material.d.ts → levels/material.d.ts} +0 -0
@@ -0,0 +1,51 @@
1
+ import { type ComputeNode, type StorageBufferAttribute, type StorageInstancedBufferAttribute } from "three/webgpu";
2
+ import { type PoolBuffers } from "./buffers.js";
3
+ /**
4
+ * The attributes chunks are read from: matrices, colours or none (white) with the floats between instances' colours,
5
+ * and an instance count's buffer or none.
6
+ */
7
+ export interface Attributes {
8
+ readonly matrices: Storage;
9
+ readonly colors: {
10
+ readonly attribute: Storage;
11
+ readonly stride: 3 | 4;
12
+ } | null;
13
+ readonly counts: Storage | null;
14
+ }
15
+ /** A storage attribute, of either kind. */
16
+ type Storage = StorageBufferAttribute | StorageInstancedBufferAttribute;
17
+ /** A chunk the count and write passes read: its slot, its first window, its range of its attributes, and where its instance count lies. */
18
+ export interface ChunkRange {
19
+ readonly slot: number;
20
+ readonly base: number;
21
+ readonly start: number;
22
+ readonly count: number;
23
+ readonly countIndex: number;
24
+ }
25
+ /** The chunk the count and write passes read next, set before each runs. */
26
+ export declare function chunkUniforms(): {
27
+ slot: import("three/webgpu").UniformNode<"uint", number>;
28
+ base: import("three/webgpu").UniformNode<"uint", number>;
29
+ start: import("three/webgpu").UniformNode<"uint", number>;
30
+ count: import("three/webgpu").UniformNode<"uint", number>;
31
+ countIndex: import("three/webgpu").UniformNode<"uint", number>;
32
+ };
33
+ export type ChunkUniforms = ReturnType<typeof chunkUniforms>;
34
+ /** Nodes reading a chunk's attributes, for their layout; pointed at each chunk's own before its passes run. */
35
+ export declare function chunkReads({ matrices, colors, counts }: Attributes): {
36
+ matrices: import("three/webgpu").StorageBufferNode<"mat4">;
37
+ colors: {
38
+ floats: import("three/webgpu").StorageBufferNode<"float">;
39
+ stride: 4 | 3;
40
+ } | null;
41
+ counts: import("three/webgpu").StorageBufferNode<"uint"> | null;
42
+ };
43
+ export type ChunkReads = ReturnType<typeof chunkReads>;
44
+ /** Counts each window's instances of `chunk`, read by `reads`: one workgroup per window. */
45
+ export declare function countPass(pool: PoolBuffers, chunk: ChunkUniforms, reads: ChunkReads): ComputeNode;
46
+ /**
47
+ * Writes each window's instances of `chunk`, read by `reads`, into its pages, in order, and clears the room past its
48
+ * last instance on its last page, which then draw nothing: one workgroup per window.
49
+ */
50
+ export declare function writePass(pool: PoolBuffers, chunk: ChunkUniforms, reads: ChunkReads): ComputeNode;
51
+ export {};
@@ -0,0 +1,81 @@
1
+ import { Matrix4 } from "three/webgpu";
2
+ import { If, localId, mat4, storage, uniform, vec3, vec4, workgroupId } from "three/tsl";
3
+ import { maxScale } from "../../tsl.js";
4
+ import { nodes } from "./buffers.js";
5
+ import { PAGE, least, rank, workgroups } from "./workgroup.js";
6
+ // The passes that read one chunk's attributes, one workgroup per window of its range: counting its instances, and
7
+ // writing them into the pages they got (see index.ts for the order they run in).
8
+ /** The matrix of a pool index without an instance: scale 0 draws nothing. */
9
+ const nothing = new Matrix4().multiplyScalar(0);
10
+ /** The chunk the count and write passes read next, set before each runs. */
11
+ export function chunkUniforms() {
12
+ return {
13
+ slot: uniform(0, "uint"),
14
+ base: uniform(0, "uint"),
15
+ start: uniform(0, "uint"),
16
+ count: uniform(0, "uint"),
17
+ countIndex: uniform(0, "uint"),
18
+ };
19
+ }
20
+ /** Nodes reading a chunk's attributes, for their layout; pointed at each chunk's own before its passes run. */
21
+ export function chunkReads({ matrices, colors, counts }) {
22
+ return {
23
+ matrices: storage(matrices, "mat4", 0).toReadOnly(),
24
+ colors: colors && { floats: storage(colors.attribute, "float", 0).toReadOnly(), stride: colors.stride },
25
+ counts: counts && storage(counts, "uint", 0).toReadOnly(),
26
+ };
27
+ }
28
+ /**
29
+ * This lane's instance of `chunk`, read by `reads`: the lane's index in the chunk's range, its matrix (scale 0 past the
30
+ * chunk's instance count) and colour, and whether it is an instance, at a scale above 0.
31
+ */
32
+ function read(chunk, { matrices, colors, counts }) {
33
+ const index = workgroupId.x.mul(PAGE).add(localId.x).toVar();
34
+ const total = counts ? least(counts.element(chunk.countIndex), chunk.count) : chunk.count;
35
+ const m = mat4(nothing).toVar();
36
+ If(index.lessThan(total), () => void m.assign(matrices.element(chunk.start.add(index))));
37
+ const first = chunk.start.add(index).mul(colors?.stride ?? 3);
38
+ const color = colors ? vec3(colors.floats.element(first), colors.floats.element(first.add(1)), colors.floats.element(first.add(2))) : vec3(1);
39
+ return { index, matrix: m, color, live: maxScale(m).greaterThan(0) };
40
+ }
41
+ /** Counts each window's instances of `chunk`, read by `reads`: one workgroup per window. */
42
+ export function countPass(pool, chunk, reads) {
43
+ const { windows } = nodes(pool);
44
+ return workgroups(() => {
45
+ const { live } = read(chunk, reads);
46
+ const { total } = rank(live);
47
+ If(localId.x.equal(0), () => void windows.element(chunk.base.add(workgroupId.x)).assign(total));
48
+ });
49
+ }
50
+ /**
51
+ * Writes each window's instances of `chunk`, read by `reads`, into its pages, in order, and clears the room past its
52
+ * last instance on its last page, which then draw nothing: one workgroup per window.
53
+ */
54
+ export function writePass(pool, chunk, reads) {
55
+ const { windows, table, states } = nodes(pool);
56
+ const matrices = storage(pool.matrices, "mat4", 0);
57
+ const colors = storage(pool.colors, "vec4", 0);
58
+ return workgroups(() => {
59
+ /** The pool index of the chunk's instance `packed`, its index among the chunk's instances. */
60
+ const poolIndexOf = (packed) => table
61
+ .element(chunk.base.add(packed.div(PAGE)))
62
+ .mul(PAGE)
63
+ .add(packed.mod(PAGE))
64
+ .toVar();
65
+ const state = states.element(chunk.slot.mul(2)).toVar();
66
+ const { matrix, color, live } = read(chunk, reads);
67
+ const { before } = rank(live);
68
+ const packed = windows.element(chunk.base.add(workgroupId.x)).add(before).toVar();
69
+ // Instances past the pages the chunk got are left out.
70
+ If(live.and(packed.lessThan(state.y.mul(PAGE))), () => {
71
+ const into = poolIndexOf(packed);
72
+ matrices.element(into).assign(matrix);
73
+ colors.element(into).assign(vec4(color, 1));
74
+ });
75
+ If(workgroupId.x.equal(0), () => {
76
+ const tail = state.z.add(localId.x).toVar();
77
+ If(tail.lessThan(state.y.mul(PAGE)), () => void matrices.element(poolIndexOf(tail)).assign(mat4(nothing)));
78
+ });
79
+ });
80
+ }
81
+ //# sourceMappingURL=chunk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk.js","sourceRoot":"","sources":["../../../src/instanced/pages/chunk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { type Renderer, StorageBufferAttribute, StorageInstancedBufferAttribute } from "three/webgpu";
2
+ import type { Attributes, ChunkRange } from "./chunk.js";
3
+ /** A chunk to take in: its attributes and its range of them, where its instance count lies, and its InstancedLod's row. */
4
+ export interface PoolChunk extends Pick<ChunkRange, "start" | "count" | "countIndex"> {
5
+ readonly attributes: Attributes;
6
+ readonly row: number;
7
+ }
8
+ /** The page pool of a LodGpu, and the passes that fill and free it. */
9
+ export declare class InstancePagePool {
10
+ /** Room for instances, in pages of `PAGE`. */
11
+ readonly capacity: number;
12
+ readonly pages: number;
13
+ /** How many pages chunks hold, then per page held its id and its InstancedLod's row (see `PAGE_BITS`). */
14
+ readonly occupied: StorageBufferAttribute;
15
+ /** Bumped whenever the passes ran: what the pages hold changed. */
16
+ version: number;
17
+ private readonly pool;
18
+ private passes;
19
+ /** Per slot, its chunk and windows, and the generation of the chunk it last took: a slot reused in one frame still frees its pages. */
20
+ private readonly held;
21
+ private readonly generations;
22
+ private readonly free;
23
+ /** The windows no chunk counts in, and those of chunks removed, free once the passes freed their pages. */
24
+ private windows;
25
+ private releasing;
26
+ /** The slots whose chunks are taken in at the next run, and whether a chunk was removed since the last. */
27
+ private readonly due;
28
+ private removed;
29
+ /** The last read of the chunks' states, and the run it followed. */
30
+ private read;
31
+ /** Whether the pool's CPU arrays were dropped (see `releaseArrays`). */
32
+ private released;
33
+ constructor(
34
+ /** The most instances held at once. */
35
+ maxInstanceCount: number,
36
+ /** The most chunks held at once. */
37
+ maxChunkCount: number);
38
+ /** Every pool index's instance matrix, as the level meshes draw them. */
39
+ get matrices(): StorageInstancedBufferAttribute;
40
+ /** Every pool index's colour, RGB and a pad. */
41
+ get colors(): StorageInstancedBufferAttribute;
42
+ /** Whether the next run takes chunks in or frees them. */
43
+ get pending(): boolean;
44
+ /** Take `chunk` into a free slot at the next run; its slot. */
45
+ add(chunk: PoolChunk): number;
46
+ /** Take slot `slot`'s chunk in again at the next run: its attributes changed. */
47
+ change(slot: number): void;
48
+ /** Free slot `slot`; its chunk's pages go back to the pool at the next run, its windows after it. */
49
+ remove(slot: number): void;
50
+ private heldAt;
51
+ private write;
52
+ /** The first of `count` free windows, taken; null if no run of them is free. */
53
+ private take;
54
+ /** Free the windows of `freed`, merging runs that meet. */
55
+ private giveBack;
56
+ /** Take the chunks' changes in on `renderer`, if they changed since the last run. */
57
+ prepare(renderer: Renderer): void;
58
+ /** Run slot `slot`'s chunk's `pass`, one workgroup per window of its range. */
59
+ private run;
60
+ /**
61
+ * The instances the chunks of `slots` hold, once every one has been taken in; null while changes wait for the passes
62
+ * or chunks changed meanwhile. Throws if a chunk lacks pages. Reads the GPU's progress back.
63
+ */
64
+ status(renderer: Renderer, slots: readonly number[]): Promise<number | null>;
65
+ /** The chunks' states as the GPU holds them after run `version`: one read back for every InstancedLod asking. */
66
+ private statesAt;
67
+ dispose(): void;
68
+ }
69
+ /**
70
+ * Drop the CPU arrays of `attributes`, buffers only the GPU writes, once a pass has run with them: they are never read
71
+ * again, and they are most of what they cost on the CPU. This relies on three never uploading them again (as of three
72
+ * r186): nothing marks them for an update, and a LodGpu's renderer, initialised, made each buffer as the pass ran.
73
+ */
74
+ export declare function releaseArrays(attributes: readonly StorageInstancedBufferAttribute[]): void;
@@ -0,0 +1,269 @@
1
+ import { StorageBufferAttribute, StorageInstancedBufferAttribute } from "three/webgpu";
2
+ import { at } from "../../at.js";
3
+ import { PAGE_BITS } from "./buffers.js";
4
+ import { PoolPasses } from "./passes.js";
5
+ import { PAGE } from "./workgroup.js";
6
+ // Every instance of every InstancedLod of a LodGpu lives in its page pool: fixed pages of `PAGE` instances, which chunks,
7
+ // from the CPU or the GPU, are copied into, and which updateInstance visits one workgroup per page (see update.ts).
8
+ //
9
+ // In the first render after chunks were added, changed or removed, these passes run: one workgroup
10
+ // walks the chunk slots and pushes every removed or changed chunk's pages back on the free stack; per chunk taken in, a
11
+ // pass with one workgroup per window of `PAGE` of its range counts the window's instances, those at a scale above 0 (an
12
+ // app's pass marks "no instance" with scale 0); one workgroup then gives every such chunk the pages its instances need,
13
+ // turning its windows' counts into where their instances start; per chunk again, a pass writes each instance into its
14
+ // page, so a chunk's instances fill its pages in order, a spot without an instance costs no room, and the room past its
15
+ // last instance draws nothing; last, one workgroup lists every page chunks hold, with its InstancedLod's row. That
16
+ // render is the only time a chunk's attributes are read. A chunk that finds the stack short holds the pages it got, its
17
+ // instances clamped to them, until it is removed; `status` reports it. The CPU never learns a count: it knows only
18
+ // which slots hold chunks and which windows they count in, and the GPU knows what each got.
19
+ /** Windows of `PAGE` spots per page of instances that chunks may span: chunks hold far more spots than instances. */
20
+ const WINDOWS_PER_PAGE = 16;
21
+ /** WebGPU's guaranteed maxStorageBufferBindingSize: the pool's matrices are one binding. */
22
+ const MAX_BINDING = 128 * 2 ** 20;
23
+ /** The page pool of a LodGpu, and the passes that fill and free it. */
24
+ export class InstancePagePool {
25
+ /** Room for instances, in pages of `PAGE`. */
26
+ capacity;
27
+ pages;
28
+ /** How many pages chunks hold, then per page held its id and its InstancedLod's row (see `PAGE_BITS`). */
29
+ occupied;
30
+ /** Bumped whenever the passes ran: what the pages hold changed. */
31
+ version = 0;
32
+ pool;
33
+ passes = null;
34
+ /** Per slot, its chunk and windows, and the generation of the chunk it last took: a slot reused in one frame still frees its pages. */
35
+ held;
36
+ generations;
37
+ free = [];
38
+ /** The windows no chunk counts in, and those of chunks removed, free once the passes freed their pages. */
39
+ windows;
40
+ releasing = [];
41
+ /** The slots whose chunks are taken in at the next run, and whether a chunk was removed since the last. */
42
+ due = new Set();
43
+ removed = false;
44
+ /** The last read of the chunks' states, and the run it followed. */
45
+ read = null;
46
+ /** Whether the pool's CPU arrays were dropped (see `releaseArrays`). */
47
+ released = false;
48
+ constructor(
49
+ /** The most instances held at once. */
50
+ maxInstanceCount,
51
+ /** The most chunks held at once. */
52
+ maxChunkCount) {
53
+ for (const [name, value] of [
54
+ ["maxInstanceCount", maxInstanceCount],
55
+ ["maxChunkCount", maxChunkCount],
56
+ ]) {
57
+ if (!Number.isInteger(value) || value < 1)
58
+ throw new RangeError(`LodGpu: ${name} must be a positive integer, got ${value}`);
59
+ }
60
+ // A part-filled page per chunk besides the pages that fill.
61
+ const pages = maxChunkCount + Math.ceil(maxInstanceCount / PAGE);
62
+ if (pages >= 2 ** PAGE_BITS)
63
+ throw new RangeError(`LodGpu: ${pages} pages of ${PAGE} instances outgrow the ${2 ** PAGE_BITS} a pool lists: lower maxInstanceCount or maxChunkCount`);
64
+ if (pages * PAGE * 64 > MAX_BINDING)
65
+ throw new RangeError(`LodGpu: the matrices of ${pages} pages of ${PAGE} instances outgrow a storage binding of ${MAX_BINDING} bytes: lower maxInstanceCount or maxChunkCount`);
66
+ const windows = WINDOWS_PER_PAGE * pages;
67
+ this.pages = pages;
68
+ this.capacity = pages * PAGE;
69
+ // Popped from the end: page 0 first.
70
+ const stack = new Uint32Array(pages + 1);
71
+ stack[0] = pages;
72
+ for (let i = 0; i < pages; i++)
73
+ stack[i + 1] = pages - 1 - i;
74
+ const words = (length, itemSize = 1) => new StorageBufferAttribute(new Uint32Array(length * itemSize), itemSize);
75
+ this.pool = {
76
+ pages,
77
+ slots: maxChunkCount,
78
+ stack: new StorageBufferAttribute(stack, 1),
79
+ table: words(windows),
80
+ windows: words(windows),
81
+ sources: words(maxChunkCount, 4),
82
+ states: words(2 * maxChunkCount, 4),
83
+ occupied: words(pages + 1),
84
+ matrices: new StorageInstancedBufferAttribute(new Float32Array(this.capacity * 16), 16),
85
+ colors: new StorageInstancedBufferAttribute(new Float32Array(this.capacity * 4), 4),
86
+ };
87
+ this.occupied = this.pool.occupied;
88
+ this.windows = [{ first: 0, count: windows }];
89
+ this.held = Array.from({ length: maxChunkCount }, () => null);
90
+ this.generations = new Uint32Array(maxChunkCount);
91
+ for (let slot = maxChunkCount - 1; slot >= 0; slot--)
92
+ this.free.push(slot);
93
+ }
94
+ /** Every pool index's instance matrix, as the level meshes draw them. */
95
+ get matrices() {
96
+ return this.pool.matrices;
97
+ }
98
+ /** Every pool index's colour, RGB and a pad. */
99
+ get colors() {
100
+ return this.pool.colors;
101
+ }
102
+ /** Whether the next run takes chunks in or frees them. */
103
+ get pending() {
104
+ return this.due.size > 0 || this.removed;
105
+ }
106
+ /** Take `chunk` into a free slot at the next run; its slot. */
107
+ add(chunk) {
108
+ const slot = this.free.pop();
109
+ if (slot === undefined)
110
+ throw new Error(`InstancedLod: all ${this.pool.slots} chunk slots are taken: raise LodGpu's maxChunkCount`);
111
+ const windows = Math.ceil(chunk.count / PAGE);
112
+ const base = this.take(windows);
113
+ if (base === null) {
114
+ this.free.push(slot);
115
+ throw new Error(`InstancedLod: chunks span more than the pool's ${this.pool.table.count} windows of ${PAGE} spots: raise LodGpu's maxInstanceCount`);
116
+ }
117
+ this.held[slot] = { chunk, base, windows };
118
+ this.change(slot);
119
+ return slot;
120
+ }
121
+ /** Take slot `slot`'s chunk in again at the next run: its attributes changed. */
122
+ change(slot) {
123
+ const { base, windows, chunk } = this.heldAt(slot);
124
+ const generation = at(this.generations, slot) + 1;
125
+ this.generations[slot] = generation;
126
+ this.write(slot, [base, windows, generation, chunk.row + 1]);
127
+ this.due.add(slot);
128
+ }
129
+ /** Free slot `slot`; its chunk's pages go back to the pool at the next run, its windows after it. */
130
+ remove(slot) {
131
+ const { base, windows } = this.heldAt(slot);
132
+ this.held[slot] = null;
133
+ this.releasing.push({ first: base, count: windows });
134
+ this.write(slot, [0, 0, at(this.generations, slot), 0]);
135
+ this.due.delete(slot);
136
+ this.free.push(slot);
137
+ this.removed = true;
138
+ }
139
+ heldAt(slot) {
140
+ const held = this.held[slot];
141
+ if (!held)
142
+ throw new Error(`InstancedLod: chunk slot ${slot} holds no chunk`);
143
+ return held;
144
+ }
145
+ write(slot, values) {
146
+ const { sources } = this.pool;
147
+ sources.array.set(values, slot * 4);
148
+ sources.addUpdateRange(slot * 4, 4);
149
+ sources.needsUpdate = true;
150
+ }
151
+ /** The first of `count` free windows, taken; null if no run of them is free. */
152
+ take(count) {
153
+ if (count === 0)
154
+ return 0;
155
+ const run = this.windows.find((each) => each.count >= count);
156
+ if (!run)
157
+ return null;
158
+ const first = run.first;
159
+ run.first += count;
160
+ run.count -= count;
161
+ if (run.count === 0)
162
+ this.windows.splice(this.windows.indexOf(run), 1);
163
+ return first;
164
+ }
165
+ /** Free the windows of `freed`, merging runs that meet. */
166
+ giveBack(freed) {
167
+ if (freed.length === 0)
168
+ return;
169
+ const runs = [...this.windows, ...freed.filter((run) => run.count > 0)].sort((a, b) => a.first - b.first);
170
+ const merged = [];
171
+ for (const run of runs) {
172
+ const last = merged.at(-1);
173
+ if (last && last.first + last.count === run.first)
174
+ last.count += run.count;
175
+ else
176
+ merged.push({ ...run });
177
+ }
178
+ this.windows = merged;
179
+ }
180
+ /** Take the chunks' changes in on `renderer`, if they changed since the last run. */
181
+ prepare(renderer) {
182
+ if (!this.pending)
183
+ return;
184
+ const passes = (this.passes ??= new PoolPasses(this.pool));
185
+ // The free pass reads the windows of chunks removed since the last run: they serve chunks taken in after it.
186
+ const freed = this.releasing;
187
+ this.releasing = [];
188
+ renderer.compute(passes.free);
189
+ for (const slot of this.due)
190
+ this.run(renderer, passes, slot, "count");
191
+ renderer.compute(passes.allocate);
192
+ for (const slot of this.due)
193
+ this.run(renderer, passes, slot, "write");
194
+ renderer.compute(passes.occupy);
195
+ this.due.clear();
196
+ this.removed = false;
197
+ this.version++;
198
+ this.giveBack(freed);
199
+ if (!this.released)
200
+ releaseArrays([this.pool.matrices, this.pool.colors]);
201
+ this.released = true;
202
+ }
203
+ /** Run slot `slot`'s chunk's `pass`, one workgroup per window of its range. */
204
+ run(renderer, passes, slot, pass) {
205
+ const { chunk, base, windows } = this.heldAt(slot);
206
+ if (windows === 0)
207
+ return;
208
+ const { attributes, start, count, countIndex } = chunk;
209
+ renderer.compute(passes.chunkPass(pass, attributes, { slot, base, start, count, countIndex }), [windows, 1, 1]);
210
+ }
211
+ /**
212
+ * The instances the chunks of `slots` hold, once every one has been taken in; null while changes wait for the passes
213
+ * or chunks changed meanwhile. Throws if a chunk lacks pages. Reads the GPU's progress back.
214
+ */
215
+ async status(renderer, slots) {
216
+ if (this.pending)
217
+ return null;
218
+ if (slots.length === 0)
219
+ return 0;
220
+ const version = this.version;
221
+ const states = await this.statesAt(renderer, version);
222
+ if (version !== this.version || this.pending)
223
+ return null;
224
+ let instances = 0;
225
+ let short = 0;
226
+ let got = 0;
227
+ let needed = 0;
228
+ for (const slot of slots) {
229
+ const base = slot * 8;
230
+ if (states[base] !== this.generations[slot])
231
+ return null;
232
+ instances += at(states, base + 2);
233
+ if (at(states, base + 1) === at(states, base + 3))
234
+ continue;
235
+ short++;
236
+ got += at(states, base + 1);
237
+ needed += at(states, base + 3);
238
+ }
239
+ if (short > 0) {
240
+ throw new Error(`InstancedLod: ${short} chunk${short === 1 ? "" : "s"} lack pages, holding ${got} of the ${needed} pages they need: raise LodGpu's maxInstanceCount (its pool has ${this.pool.pages} pages of ${PAGE})`);
241
+ }
242
+ return instances;
243
+ }
244
+ /** The chunks' states as the GPU holds them after run `version`: one read back for every InstancedLod asking. */
245
+ statesAt(renderer, version) {
246
+ if (this.read?.version !== version) {
247
+ const promise = renderer.getArrayBufferAsync(this.pool.states).then((buffer) => new Uint32Array(buffer));
248
+ this.read = { version, promise };
249
+ }
250
+ return this.read.promise;
251
+ }
252
+ dispose() {
253
+ const { pool } = this;
254
+ for (const attribute of [pool.stack, pool.table, pool.windows, pool.sources, pool.states, pool.occupied, pool.matrices, pool.colors])
255
+ attribute.dispose();
256
+ this.passes?.dispose();
257
+ this.passes = null;
258
+ }
259
+ }
260
+ /**
261
+ * Drop the CPU arrays of `attributes`, buffers only the GPU writes, once a pass has run with them: they are never read
262
+ * again, and they are most of what they cost on the CPU. This relies on three never uploading them again (as of three
263
+ * r186): nothing marks them for an update, and a LodGpu's renderer, initialised, made each buffer as the pass ran.
264
+ */
265
+ export function releaseArrays(attributes) {
266
+ for (const attribute of attributes)
267
+ attribute.array = new Float32Array(0);
268
+ }
269
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/instanced/pages/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { ComputeNode } from "three/webgpu";
2
+ import type { PoolBuffers } from "./buffers.js";
3
+ import { type Attributes, type ChunkRange } from "./chunk.js";
4
+ /**
5
+ * A pool's passes: built once, the count and write passes once per layout of the attributes they read (colours of a
6
+ * stride or none, counts or none: six at most), and pointed at a chunk's attributes and range as it is about to run
7
+ * (see `chunkPass`). They run at once as the pool prepares, never queued, so no pass still waits to run when the next
8
+ * chunk is set.
9
+ */
10
+ export declare class PoolPasses {
11
+ private readonly pool;
12
+ readonly free: ComputeNode;
13
+ readonly allocate: ComputeNode;
14
+ readonly occupy: ComputeNode;
15
+ private readonly uniforms;
16
+ private readonly byLayout;
17
+ constructor(pool: PoolBuffers);
18
+ /** `pass` for the chunk of `attributes` and `range`, pointed at them: run it before pointing it at another. */
19
+ chunkPass(pass: "count" | "write", attributes: Attributes, range: ChunkRange): ComputeNode;
20
+ dispose(): void;
21
+ }
@@ -0,0 +1,52 @@
1
+ import { chunkReads, chunkUniforms, countPass, writePass } from "./chunk.js";
2
+ import { allocatePass, freePass, occupyPass } from "./slots.js";
3
+ /**
4
+ * A pool's passes: built once, the count and write passes once per layout of the attributes they read (colours of a
5
+ * stride or none, counts or none: six at most), and pointed at a chunk's attributes and range as it is about to run
6
+ * (see `chunkPass`). They run at once as the pool prepares, never queued, so no pass still waits to run when the next
7
+ * chunk is set.
8
+ */
9
+ export class PoolPasses {
10
+ pool;
11
+ free;
12
+ allocate;
13
+ occupy;
14
+ uniforms = chunkUniforms();
15
+ byLayout = new Map();
16
+ constructor(pool) {
17
+ this.pool = pool;
18
+ this.free = freePass(pool);
19
+ this.allocate = allocatePass(pool);
20
+ this.occupy = occupyPass(pool);
21
+ }
22
+ /** `pass` for the chunk of `attributes` and `range`, pointed at them: run it before pointing it at another. */
23
+ chunkPass(pass, attributes, range) {
24
+ const layout = `${attributes.colors?.stride ?? 0}/${attributes.counts ? 1 : 0}`;
25
+ let passes = this.byLayout.get(layout);
26
+ if (!passes) {
27
+ const reads = chunkReads(attributes);
28
+ passes = { reads, count: countPass(this.pool, this.uniforms, reads), write: writePass(this.pool, this.uniforms, reads) };
29
+ this.byLayout.set(layout, passes);
30
+ }
31
+ const { reads } = passes;
32
+ reads.matrices.value = attributes.matrices;
33
+ if (reads.colors && attributes.colors)
34
+ reads.colors.floats.value = attributes.colors.attribute;
35
+ if (reads.counts && attributes.counts)
36
+ reads.counts.value = attributes.counts;
37
+ const { uniforms } = this;
38
+ uniforms.slot.value = range.slot;
39
+ uniforms.base.value = range.base;
40
+ uniforms.start.value = range.start;
41
+ uniforms.count.value = range.count;
42
+ uniforms.countIndex.value = range.countIndex;
43
+ return passes[pass];
44
+ }
45
+ dispose() {
46
+ const chunkNodes = [...this.byLayout.values()].flatMap(({ count, write }) => [count, write]);
47
+ for (const node of [this.free, this.allocate, this.occupy, ...chunkNodes])
48
+ node.dispose();
49
+ this.byLayout.clear();
50
+ }
51
+ }
52
+ //# sourceMappingURL=passes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passes.js","sourceRoot":"","sources":["../../../src/instanced/pages/passes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAqD,MAAM,YAAY,CAAC;AAChI,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAYhE;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IAOQ;IANpB,IAAI,CAAc;IAClB,QAAQ,CAAc;IACtB,MAAM,CAAc;IACZ,QAAQ,GAAG,aAAa,EAAE,CAAC;IAC3B,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAE3D,YAA6B,IAAiB;QAAjB,SAAI,GAAJ,IAAI,CAAa;QAC5C,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,+GAA+G;IAC/G,SAAS,CAAC,IAAuB,EAAE,UAAsB,EAAE,KAAiB;QAC1E,MAAM,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,IAAI,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;YACzH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACpC,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC;QAC3C,IAAI,KAAK,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM;YAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC;QAC/F,IAAI,KAAK,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM;YAAE,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC;QAC9E,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;QACjC,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACnC,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACnC,QAAQ,CAAC,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC;QAC7C,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,OAAO;QACL,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QAC7F,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC;YAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QAC1F,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import type { ComputeNode } from "three/webgpu";
2
+ import { type PoolBuffers } from "./buffers.js";
3
+ /** Frees the pages of every chunk removed or changed since the last run: one workgroup. */
4
+ export declare function freePass(pool: PoolBuffers): ComputeNode;
5
+ /**
6
+ * Gives new chunks the pages their instances need, turning their window counts into where their instances start: one
7
+ * workgroup. Under a short stack, which chunks get its last pages is a race.
8
+ */
9
+ export declare function allocatePass(pool: PoolBuffers): ComputeNode;
10
+ /** Lists every page chunks hold, with its InstancedLod's row, for updateInstance to visit: one workgroup. */
11
+ export declare function occupyPass(pool: PoolBuffers): ComputeNode;