@forgeax/engine-render 0.1.32 → 0.1.34

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 (624) hide show
  1. package/README.md +1374 -142
  2. package/dist/assembly/analytic-fog-registration.d.ts +3 -0
  3. package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
  4. package/dist/assembly/backend-contract.d.ts +2 -0
  5. package/dist/assembly/backend-contract.d.ts.map +1 -1
  6. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  7. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  8. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  9. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  10. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  11. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  12. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  13. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  15. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  16. package/dist/assembly/factory.d.ts +1 -1
  17. package/dist/assembly/factory.d.ts.map +1 -1
  18. package/dist/assembly/fxaa-registration.d.ts +4 -0
  19. package/dist/assembly/fxaa-registration.d.ts.map +1 -0
  20. package/dist/assembly/host-contract.d.ts +3 -3
  21. package/dist/assembly/host-contract.d.ts.map +1 -1
  22. package/dist/assembly/lod-observation.d.ts +4 -0
  23. package/dist/assembly/lod-observation.d.ts.map +1 -0
  24. package/dist/assembly/material/assembly.d.ts.map +1 -1
  25. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  26. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  27. package/dist/assembly/material-shader-policy.d.ts +16 -2
  28. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  29. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  30. package/dist/assembly/motion-blur-registration.d.ts +3 -0
  31. package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
  32. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  33. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  34. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  35. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  36. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  37. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  38. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  39. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  40. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  41. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  42. package/dist/assembly/renderer-inspection.d.ts +11 -0
  43. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  44. package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
  45. package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  47. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  48. package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
  49. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -1
  50. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  51. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  52. package/dist/assembly/webgpu-ready.d.ts +2 -2
  53. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  54. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  55. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  56. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  57. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  58. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  59. package/dist/authoring.mjs +1 -1
  60. package/dist/barrel-distortion.d.ts +47 -0
  61. package/dist/barrel-distortion.d.ts.map +1 -0
  62. package/dist/bloom-admission.d.ts +13 -0
  63. package/dist/bloom-admission.d.ts.map +1 -0
  64. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  65. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  66. package/dist/{chunk-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
  67. package/dist/chunk-HEB564WF.mjs.map +1 -0
  68. package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
  69. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  70. package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
  71. package/dist/{chunk-S665NJNF.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  72. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  73. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  74. package/dist/{chunk-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
  75. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  76. package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
  77. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  78. package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
  79. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  80. package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
  81. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  82. package/dist/cloud/density.d.ts +55 -0
  83. package/dist/cloud/density.d.ts.map +1 -0
  84. package/dist/cloud/extract.d.ts +25 -0
  85. package/dist/cloud/extract.d.ts.map +1 -0
  86. package/dist/cloud/feature.d.ts +57 -0
  87. package/dist/cloud/feature.d.ts.map +1 -0
  88. package/dist/cloud/frame-context.d.ts +8 -0
  89. package/dist/cloud/frame-context.d.ts.map +1 -0
  90. package/dist/cloud/inspection.d.ts +59 -0
  91. package/dist/cloud/inspection.d.ts.map +1 -0
  92. package/dist/cloud/optics.d.ts +56 -0
  93. package/dist/cloud/optics.d.ts.map +1 -0
  94. package/dist/cloud/parameters.d.ts +73 -0
  95. package/dist/cloud/parameters.d.ts.map +1 -0
  96. package/dist/cloud/resources.d.ts +60 -0
  97. package/dist/cloud/resources.d.ts.map +1 -0
  98. package/dist/cloud/shadow.d.ts +42 -0
  99. package/dist/cloud/shadow.d.ts.map +1 -0
  100. package/dist/cloud/temporal.d.ts +74 -0
  101. package/dist/cloud/temporal.d.ts.map +1 -0
  102. package/dist/components/atmosphere.d.ts +2 -0
  103. package/dist/components/atmosphere.d.ts.map +1 -1
  104. package/dist/components/barrel-distortion.d.ts +13 -0
  105. package/dist/components/barrel-distortion.d.ts.map +1 -0
  106. package/dist/components/camera.d.ts +20 -4
  107. package/dist/components/camera.d.ts.map +1 -1
  108. package/dist/components/cloud-layer.d.ts +29 -0
  109. package/dist/components/cloud-layer.d.ts.map +1 -0
  110. package/dist/components/index.d.ts +2 -0
  111. package/dist/components/index.d.ts.map +1 -1
  112. package/dist/components/instances.d.ts +20 -6
  113. package/dist/components/instances.d.ts.map +1 -1
  114. package/dist/components/mesh-filter.d.ts +6 -5
  115. package/dist/components/mesh-filter.d.ts.map +1 -1
  116. package/dist/components/motion-blur.d.ts +1 -0
  117. package/dist/components/motion-blur.d.ts.map +1 -1
  118. package/dist/construct-renderer.d.ts +1 -1
  119. package/dist/construct-renderer.d.ts.map +1 -1
  120. package/dist/construct-renderer.mjs +9751 -3528
  121. package/dist/construct-renderer.mjs.map +1 -1
  122. package/dist/device/gpu-residency.d.ts +6 -0
  123. package/dist/device/gpu-residency.d.ts.map +1 -1
  124. package/dist/dynamic-geometry.d.ts +5 -1
  125. package/dist/dynamic-geometry.d.ts.map +1 -1
  126. package/dist/environment/analytic-fog.d.ts +6 -0
  127. package/dist/environment/analytic-fog.d.ts.map +1 -0
  128. package/dist/errors/cloud.d.ts +59 -0
  129. package/dist/errors/cloud.d.ts.map +1 -0
  130. package/dist/errors/render.d.ts +23 -5
  131. package/dist/errors/render.d.ts.map +1 -1
  132. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  133. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  134. package/dist/extract/camera.d.ts.map +1 -1
  135. package/dist/extract/contracts.d.ts +12 -1
  136. package/dist/extract/contracts.d.ts.map +1 -1
  137. package/dist/extract/environment.d.ts +2 -0
  138. package/dist/extract/environment.d.ts.map +1 -1
  139. package/dist/features/barrel-distortion.d.ts +29 -0
  140. package/dist/features/barrel-distortion.d.ts.map +1 -0
  141. package/dist/features/error-reporting.d.ts +17 -0
  142. package/dist/features/error-reporting.d.ts.map +1 -0
  143. package/dist/features/host.d.ts +15 -0
  144. package/dist/features/host.d.ts.map +1 -1
  145. package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
  146. package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
  147. package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
  148. package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
  149. package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
  150. package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
  151. package/dist/features/plan.d.ts +15 -4
  152. package/dist/features/plan.d.ts.map +1 -1
  153. package/dist/features/prepared-gpu-work.d.ts +9 -5
  154. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  155. package/dist/features/render-graph-compute.d.ts.map +1 -1
  156. package/dist/features/render-graph-contribution.d.ts +5 -0
  157. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  158. package/dist/features/render-graph-raster.d.ts +1 -0
  159. package/dist/features/render-graph-raster.d.ts.map +1 -1
  160. package/dist/features/targets.d.ts +2 -0
  161. package/dist/features/targets.d.ts.map +1 -1
  162. package/dist/features/types.d.ts +44 -0
  163. package/dist/features/types.d.ts.map +1 -1
  164. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  165. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  166. package/dist/gpu-dirty-ranges.d.ts +11 -0
  167. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  168. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  169. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  170. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  171. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  172. package/dist/gpu-driven/prepared-draw.d.ts +7 -0
  173. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  174. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  175. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  176. package/dist/gpu-driven/production-raster.d.ts +50 -4
  177. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  178. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  179. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  180. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  181. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  182. package/dist/gpu-driven/view-gpu.d.ts +35 -2
  183. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  184. package/dist/gpu-scene.d.ts +11 -1
  185. package/dist/gpu-scene.d.ts.map +1 -1
  186. package/dist/hdrp-buffers.d.ts +2 -2
  187. package/dist/hdrp-buffers.d.ts.map +1 -1
  188. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  189. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  190. package/dist/index.d.ts +31 -8
  191. package/dist/index.d.ts.map +1 -1
  192. package/dist/index.mjs +258 -8
  193. package/dist/index.mjs.map +1 -1
  194. package/dist/inspection-types.d.ts +178 -3
  195. package/dist/inspection-types.d.ts.map +1 -1
  196. package/dist/instance-buffer-cache.d.ts +4 -4
  197. package/dist/instance-buffer-cache.d.ts.map +1 -1
  198. package/dist/instances.d.ts +49 -94
  199. package/dist/instances.d.ts.map +1 -1
  200. package/dist/internal.mjs +7 -7
  201. package/dist/pbr-pipeline.d.ts +19 -1
  202. package/dist/pbr-pipeline.d.ts.map +1 -1
  203. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  204. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  205. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  206. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  207. package/dist/pipeline/standard-output/types.d.ts +4 -2
  208. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  209. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  210. package/dist/pipeline/standard-post.d.ts +28 -19
  211. package/dist/pipeline/standard-post.d.ts.map +1 -1
  212. package/dist/pipeline-builder.d.ts +1 -1
  213. package/dist/pipeline-builder.d.ts.map +1 -1
  214. package/dist/pipeline-spec.d.ts +2 -2
  215. package/dist/plugin.d.ts.map +1 -1
  216. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  217. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  218. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  219. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  220. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  221. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  222. package/dist/record/fold-buckets.d.ts +95 -0
  223. package/dist/record/fold-buckets.d.ts.map +1 -0
  224. package/dist/record/fold-instance-buffer.d.ts +6 -0
  225. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  226. package/dist/record/frame-lighting.d.ts +1 -0
  227. package/dist/record/frame-lighting.d.ts.map +1 -1
  228. package/dist/record/frame-snapshot.d.ts +40 -3
  229. package/dist/record/frame-snapshot.d.ts.map +1 -1
  230. package/dist/record/frame-targets.d.ts.map +1 -1
  231. package/dist/record/frame.d.ts +14 -62
  232. package/dist/record/frame.d.ts.map +1 -1
  233. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  234. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  235. package/dist/record/gpu-timing.d.ts +8 -0
  236. package/dist/record/gpu-timing.d.ts.map +1 -1
  237. package/dist/record/main-pass-geometry.d.ts +21 -5
  238. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  239. package/dist/record/main-pass-material.d.ts +7 -1
  240. package/dist/record/main-pass-material.d.ts.map +1 -1
  241. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  242. package/dist/record/main-pass.d.ts +13 -2
  243. package/dist/record/main-pass.d.ts.map +1 -1
  244. package/dist/record/mesh-ssbo.d.ts +6 -5
  245. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  246. package/dist/record/motion-blur-receipt.d.ts +11 -0
  247. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  248. package/dist/record/probe-blend-buffer.d.ts +16 -0
  249. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  250. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  251. package/dist/record/render-context.d.ts +34 -31
  252. package/dist/record/render-context.d.ts.map +1 -1
  253. package/dist/record/shadow-pass.d.ts +2 -0
  254. package/dist/record/shadow-pass.d.ts.map +1 -1
  255. package/dist/record/skybox-post-pass.d.ts +6 -4
  256. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  257. package/dist/record/typed-frame-graph.d.ts +22 -2
  258. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  259. package/dist/record/view-ubo.d.ts +11 -3
  260. package/dist/record/view-ubo.d.ts.map +1 -1
  261. package/dist/record/volume-params.d.ts +9 -0
  262. package/dist/record/volume-params.d.ts.map +1 -0
  263. package/dist/recovery/render-system-candidate.d.ts +10 -0
  264. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  265. package/dist/reflection/record-owner.d.ts.map +1 -1
  266. package/dist/render-contract.d.ts +66 -8
  267. package/dist/render-contract.d.ts.map +1 -1
  268. package/dist/render-graph-primitives.d.ts.map +1 -1
  269. package/dist/render-pipeline.d.ts +106 -3
  270. package/dist/render-pipeline.d.ts.map +1 -1
  271. package/dist/render-system-extract-tail.d.ts +3 -2
  272. package/dist/render-system-extract-tail.d.ts.map +1 -1
  273. package/dist/render-system-extract.d.ts +24 -10
  274. package/dist/render-system-extract.d.ts.map +1 -1
  275. package/dist/render-system-presentation.d.ts +23 -0
  276. package/dist/render-system-presentation.d.ts.map +1 -0
  277. package/dist/render-system-producer-roots.d.ts +10 -0
  278. package/dist/render-system-producer-roots.d.ts.map +1 -0
  279. package/dist/render-system-residency.d.ts +12 -0
  280. package/dist/render-system-residency.d.ts.map +1 -0
  281. package/dist/render-system.d.ts +26 -15
  282. package/dist/render-system.d.ts.map +1 -1
  283. package/dist/scene/probe-blend.d.ts +27 -0
  284. package/dist/scene/probe-blend.d.ts.map +1 -1
  285. package/dist/scene/render-scene.d.ts +14 -5
  286. package/dist/scene/render-scene.d.ts.map +1 -1
  287. package/dist/ssao-buffers.d.ts +9 -0
  288. package/dist/ssao-buffers.d.ts.map +1 -1
  289. package/dist/surface/dynamic-input.d.ts +133 -0
  290. package/dist/surface/dynamic-input.d.ts.map +1 -0
  291. package/dist/surface/gpu-driven.d.ts +41 -0
  292. package/dist/surface/gpu-driven.d.ts.map +1 -0
  293. package/dist/surface/submission-observation.d.ts +136 -0
  294. package/dist/surface/submission-observation.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  296. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  297. package/dist/temporal/frame.d.ts +7 -0
  298. package/dist/temporal/frame.d.ts.map +1 -1
  299. package/dist/temporal/gpu.d.ts +13 -1
  300. package/dist/temporal/gpu.d.ts.map +1 -1
  301. package/dist/temporal/index.mjs +5 -5
  302. package/dist/temporal/inspection.d.ts.map +1 -1
  303. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  304. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  305. package/dist/temporal/view.d.ts +6 -1
  306. package/dist/temporal/view.d.ts.map +1 -1
  307. package/dist/transmission/single-layer-medium.d.ts +89 -0
  308. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  309. package/dist/typed-render-graph-primitives.d.ts +24 -9
  310. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  311. package/dist/volume/component.d.ts +9 -5
  312. package/dist/volume/component.d.ts.map +1 -1
  313. package/dist/volume/extract.d.ts +1 -1
  314. package/dist/volume/extract.d.ts.map +1 -1
  315. package/dist/volume/inspection.d.ts +2 -0
  316. package/dist/volume/inspection.d.ts.map +1 -1
  317. package/dist/volume/passes.d.ts +4 -1
  318. package/dist/volume/passes.d.ts.map +1 -1
  319. package/dist/volume/resources.d.ts.map +1 -1
  320. package/dist/volume/temporal.d.ts +3 -1
  321. package/dist/volume/temporal.d.ts.map +1 -1
  322. package/package.json +22 -21
  323. package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
  324. package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
  325. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  326. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  327. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  328. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  329. package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
  330. package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
  331. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  332. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  333. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  334. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  335. package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
  336. package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
  337. package/src/__tests__/environment-selection.unit.test.ts +12 -0
  338. package/src/__tests__/factory-contract.integration.test.ts +626 -113
  339. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  340. package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
  341. package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +2 -1
  347. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  348. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  349. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  350. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +7 -6
  351. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
  352. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
  353. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  354. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  355. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  356. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  357. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  358. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  359. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  360. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
  361. package/src/__tests__/gpu-scene.unit.test.ts +210 -9
  362. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  363. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  364. package/src/__tests__/instances-store.unit.test.ts +105 -238
  365. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  366. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  367. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  368. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  369. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
  370. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  371. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  372. package/src/__tests__/motion-blur-compute.dawn.test.ts +589 -0
  373. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  374. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  375. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  376. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  377. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
  378. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  379. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
  380. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  381. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  382. package/src/__tests__/public-surface.test-d.ts +8 -0
  383. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  384. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  385. package/src/__tests__/render-error-code-owner.test-d.ts +9 -0
  386. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  387. package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
  388. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  389. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  390. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
  391. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  392. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  393. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +37 -6
  394. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  395. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  396. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  397. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  398. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  399. package/src/__tests__/renderer-frame-transaction.integration.test.ts +33 -11
  400. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  401. package/src/__tests__/shader-manifest-fixture.ts +4 -4
  402. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  403. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  404. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  405. package/src/__tests__/skinned-shadow-caster.test.ts +17 -0
  406. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  407. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  408. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  409. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  410. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  411. package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
  412. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  413. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  414. package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
  415. package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
  416. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  417. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  418. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  419. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  420. package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
  421. package/src/__tests__/temporal-view.unit.test.ts +2 -1
  422. package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
  423. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  424. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  425. package/src/__tests__/volume-optics-oracle.unit.test.ts +7 -3
  426. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
  427. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  428. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  429. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  430. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +558 -68
  431. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
  432. package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
  433. package/src/assembly/analytic-fog-registration.ts +14 -0
  434. package/src/assembly/backend-contract.ts +30 -0
  435. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  436. package/src/assembly/canvas-draw-guard.ts +11 -0
  437. package/src/assembly/cloud-shadow-entry.ts +22 -0
  438. package/src/assembly/dynamic-geometry-host.ts +65 -37
  439. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  440. package/src/assembly/factory.ts +2 -30
  441. package/src/assembly/fxaa-registration.ts +17 -0
  442. package/src/assembly/host-contract.ts +3 -3
  443. package/src/assembly/lod-observation.ts +12 -0
  444. package/src/assembly/material/assembly.ts +25 -13
  445. package/src/assembly/material/pipeline-helpers.ts +53 -12
  446. package/src/assembly/material-shader-policy.ts +55 -0
  447. package/src/assembly/material-shader-prewarm.ts +21 -10
  448. package/src/assembly/motion-blur-registration.ts +17 -0
  449. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  450. package/src/assembly/recovery/renderer-recover.ts +41 -18
  451. package/src/assembly/render-feature-post-processes.ts +54 -0
  452. package/src/assembly/renderer-facade.ts +6 -1
  453. package/src/assembly/renderer-feature-inspection.ts +8 -2
  454. package/src/assembly/renderer-frame-transaction.ts +23 -0
  455. package/src/assembly/renderer-inspection.ts +28 -0
  456. package/src/assembly/skin-palette-owner.ts +1 -1
  457. package/src/assembly/temporal-post-process-prewarm.ts +40 -0
  458. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  459. package/src/assembly/webgpu-ready-contract.ts +8 -3
  460. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  461. package/src/assembly/webgpu-ready.ts +296 -306
  462. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  463. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  464. package/src/assembly/webgpu-renderer.ts +228 -281
  465. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  466. package/src/barrel-distortion.ts +247 -0
  467. package/src/bloom-admission.ts +21 -0
  468. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  469. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  470. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  471. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  472. package/src/cloud/density.ts +600 -0
  473. package/src/cloud/extract.ts +110 -0
  474. package/src/cloud/feature.ts +1810 -0
  475. package/src/cloud/frame-context.ts +42 -0
  476. package/src/cloud/inspection.ts +130 -0
  477. package/src/cloud/optics.ts +285 -0
  478. package/src/cloud/parameters.ts +255 -0
  479. package/src/cloud/resources.ts +122 -0
  480. package/src/cloud/shadow.ts +167 -0
  481. package/src/cloud/temporal.ts +226 -0
  482. package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
  483. package/src/components/atmosphere.ts +4 -0
  484. package/src/components/barrel-distortion.ts +46 -0
  485. package/src/components/camera.ts +66 -10
  486. package/src/components/cloud-layer.ts +47 -0
  487. package/src/components/index.ts +2 -0
  488. package/src/components/instances.ts +18 -45
  489. package/src/components/mesh-filter.ts +11 -9
  490. package/src/components/motion-blur.ts +1 -0
  491. package/src/components/sprite-instances.ts +1 -1
  492. package/src/construct-renderer.ts +1 -1
  493. package/src/device/gpu-residency.ts +56 -12
  494. package/src/dynamic-geometry.ts +12 -1
  495. package/src/environment/analytic-fog.ts +44 -0
  496. package/src/environment/background.ts +2 -2
  497. package/src/errors/cloud.ts +103 -0
  498. package/src/errors/render.ts +58 -8
  499. package/src/examples/single-layer-medium-surface.ts +59 -0
  500. package/src/extract/camera.ts +35 -8
  501. package/src/extract/contracts.ts +12 -0
  502. package/src/extract/environment.ts +4 -0
  503. package/src/features/barrel-distortion.ts +172 -0
  504. package/src/features/error-reporting.ts +98 -0
  505. package/src/features/host.ts +138 -24
  506. package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
  507. package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
  508. package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
  509. package/src/features/motion-blur/motion-blur-params.ts +70 -2
  510. package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
  511. package/src/features/plan.ts +33 -8
  512. package/src/features/prepared-gpu-work.ts +86 -35
  513. package/src/features/render-graph-compute.ts +13 -5
  514. package/src/features/render-graph-contribution.ts +11 -0
  515. package/src/features/render-graph-raster.ts +45 -3
  516. package/src/features/targets.ts +66 -0
  517. package/src/features/types.ts +47 -0
  518. package/src/fullscreen-post-process-pass.ts +41 -9
  519. package/src/gpu-dirty-ranges.ts +48 -0
  520. package/src/gpu-driven/batch-topology.ts +53 -0
  521. package/src/gpu-driven/material-artifacts.ts +35 -32
  522. package/src/gpu-driven/prepared-draw.ts +27 -14
  523. package/src/gpu-driven/production-raster-material.ts +1894 -0
  524. package/src/gpu-driven/production-raster.ts +904 -787
  525. package/src/gpu-driven/resource-allocation.ts +142 -0
  526. package/src/gpu-driven/shadow-ownership.ts +71 -0
  527. package/src/gpu-driven/view-gpu.ts +181 -10
  528. package/src/gpu-scene.ts +259 -101
  529. package/src/hdrp-buffers.ts +4 -3
  530. package/src/ibl/skylight-bind-group.ts +49 -7
  531. package/src/index.ts +228 -9
  532. package/src/inspection-types.ts +222 -2
  533. package/src/instance-buffer-cache.ts +4 -4
  534. package/src/instances.ts +151 -492
  535. package/src/pbr-pipeline.ts +219 -13
  536. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  537. package/src/pipeline/standard-forward-lane.ts +313 -57
  538. package/src/pipeline/standard-output/graph.ts +8 -2
  539. package/src/pipeline/standard-output/types.ts +12 -1
  540. package/src/pipeline/standard-pipeline.ts +291 -18
  541. package/src/pipeline/standard-post.ts +397 -102
  542. package/src/pipeline-builder.ts +1 -1
  543. package/src/pipeline-spec.ts +5 -5
  544. package/src/plugin.ts +4 -0
  545. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  546. package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
  547. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  548. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  549. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  550. package/src/record/__tests__/temporal-payload.unit.test.ts +3 -2
  551. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  552. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  553. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  554. package/src/record/barrel-distortion-frame.ts +110 -0
  555. package/src/record/dynamic-geometry-consumption.ts +39 -9
  556. package/src/record/fold-buckets.ts +852 -0
  557. package/src/record/fold-instance-buffer.ts +51 -0
  558. package/src/record/frame-lighting.ts +36 -2
  559. package/src/record/frame-snapshot.ts +44 -4
  560. package/src/record/frame-targets.ts +10 -6
  561. package/src/record/frame.ts +373 -1099
  562. package/src/record/gpu-draw-receipts.ts +38 -0
  563. package/src/record/gpu-timing.ts +48 -5
  564. package/src/record/main-pass-geometry.ts +281 -83
  565. package/src/record/main-pass-material.ts +66 -4
  566. package/src/record/main-pass-sprite-draws.ts +13 -66
  567. package/src/record/main-pass.ts +156 -20
  568. package/src/record/mesh-ssbo.ts +43 -6
  569. package/src/record/motion-blur-receipt.ts +91 -0
  570. package/src/record/probe-blend-buffer.ts +180 -0
  571. package/src/record/recovery-pipeline.ts +35 -3
  572. package/src/record/render-context.ts +51 -31
  573. package/src/record/shadow-pass.ts +36 -2
  574. package/src/record/skybox-post-pass.ts +150 -200
  575. package/src/record/typed-frame-graph.ts +824 -44
  576. package/src/record/view-ubo.ts +26 -3
  577. package/src/record/volume-params.ts +225 -0
  578. package/src/recovery/render-system-candidate.ts +257 -52
  579. package/src/reflection/record-owner.ts +7 -3
  580. package/src/render-contract.ts +71 -8
  581. package/src/render-graph-primitives.ts +7 -1
  582. package/src/render-pipeline.ts +136 -1
  583. package/src/render-system-extract-tail.ts +72 -60
  584. package/src/render-system-extract.ts +117 -87
  585. package/src/render-system-presentation.ts +56 -0
  586. package/src/render-system-producer-roots.ts +96 -0
  587. package/src/render-system-residency.ts +159 -0
  588. package/src/render-system.ts +601 -482
  589. package/src/scene/probe-blend.ts +96 -4
  590. package/src/scene/render-scene.ts +431 -281
  591. package/src/ssao-buffers.ts +95 -2
  592. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  593. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  594. package/src/surface/dynamic-input.ts +658 -0
  595. package/src/surface/gpu-driven.ts +147 -0
  596. package/src/surface/submission-observation.ts +517 -0
  597. package/src/systems/skin-palette-allocator.ts +4 -1
  598. package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
  599. package/src/temporal/frame-coordinator.ts +8 -1
  600. package/src/temporal/frame.ts +20 -0
  601. package/src/temporal/gpu.ts +101 -17
  602. package/src/temporal/inspection.ts +7 -1
  603. package/src/temporal/standard-scene-data.ts +5 -0
  604. package/src/temporal/target-coverage-attachment.ts +4 -0
  605. package/src/temporal/view.ts +13 -2
  606. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  607. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  608. package/src/transmission/single-layer-medium.ts +322 -0
  609. package/src/typed-render-graph-primitives.ts +191 -50
  610. package/src/volume/component.ts +10 -10
  611. package/src/volume/extract.ts +11 -5
  612. package/src/volume/inspection.ts +3 -0
  613. package/src/volume/passes.ts +95 -8
  614. package/src/volume/resources.ts +2 -1
  615. package/src/volume/temporal.ts +11 -0
  616. package/dist/chunk-4NNZQCL3.mjs.map +0 -1
  617. package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
  618. package/dist/chunk-DRR7D3KX.mjs.map +0 -1
  619. package/dist/chunk-GWCEMDVR.mjs.map +0 -1
  620. package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
  621. package/dist/chunk-JRIPCMYC.mjs.map +0 -1
  622. package/dist/chunk-LULCA3OF.mjs +0 -1713
  623. package/dist/chunk-LULCA3OF.mjs.map +0 -1
  624. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
package/src/instances.ts CHANGED
@@ -1,50 +1,26 @@
1
+ import type { World } from '@forgeax/engine-ecs';
2
+ import { InstanceTransformsStrideMismatchError } from '@forgeax/engine-ecs/projection';
1
3
  import type { RhiErrorCode } from '@forgeax/engine-rhi';
2
- import { err, ok, type Result } from '@forgeax/engine-types';
3
4
 
4
5
  const MATRIX_STRIDE = 16;
5
- const INITIAL_CAPACITY = 1;
6
6
 
7
+ /** Renderer projection identity; never stored in a World or SceneAsset. */
7
8
  export type InstanceCollectionId = number & {
8
9
  readonly __forgeaxInstanceCollectionId: unique symbol;
9
10
  };
10
-
11
- export interface InstanceCollectionData {
11
+ export interface InstanceCollectionInfo {
12
12
  readonly collectionId: InstanceCollectionId;
13
- }
14
-
15
- export interface InstanceCollectionInfo extends InstanceCollectionData {
16
13
  readonly count: number;
17
- readonly capacity: number;
18
14
  readonly revision: number;
19
15
  }
20
-
21
16
  export interface InstanceDirtyRange {
22
17
  start: number;
23
18
  end: number;
24
19
  }
25
-
26
- /**
27
- * Choose the ranges that initialize one resident GPU allocation.
28
- *
29
- * A cache miss is not a delta upload: recovery, reassociation, and any other
30
- * new resident has uninitialized device memory. The canonical collection must
31
- * therefore be copied in full even when the current authoring revision only
32
- * records a partial dirty range. Existing residents keep the narrower ranges.
33
- */
34
- export function instanceUploadRangesForResident(
35
- activeIsNew: boolean,
36
- dirtyRanges: readonly InstanceDirtyRange[],
37
- fullRange: InstanceDirtyRange,
38
- ): readonly InstanceDirtyRange[] {
39
- return activeIsNew ? [fullRange] : dirtyRanges;
40
- }
41
-
42
20
  export interface InstanceCollectionSnapshot extends InstanceCollectionInfo {
43
21
  readonly transforms: Float32Array;
44
- readonly dirtyRanges: readonly InstanceDirtyRange[];
22
+ readonly generations: Uint32Array;
45
23
  }
46
-
47
- /** The renderer-owned submission lane selected for one collection. */
48
24
  export type InstanceSubmissionLane =
49
25
  | 'unresident'
50
26
  | 'direct-storage'
@@ -52,14 +28,8 @@ export type InstanceSubmissionLane =
52
28
  | 'direct-uniform'
53
29
  | 'chunked-uniform'
54
30
  | 'unavailable';
55
-
56
- /** Backend identity carried by collection residency and failure facts. */
57
31
  export type InstanceBackendKind = 'webgpu' | 'wgpu-native' | 'wgpu-webgl2' | 'null' | 'unknown';
58
-
59
- /** Closed record-stage failure vocabulary for collection residency. */
60
32
  export type InstanceCollectionFailureCode = RhiErrorCode | 'queue-write-buffer-failed';
61
-
62
- /** Typed producer facts retained when a collection cannot be admitted. */
63
33
  export interface InstanceCollectionFailureFacts {
64
34
  readonly requestedBytes: number;
65
35
  readonly supportedBytes: number | undefined;
@@ -68,29 +38,9 @@ export interface InstanceCollectionFailureFacts {
68
38
  readonly cause: string;
69
39
  readonly recovery: string;
70
40
  }
71
-
72
- function instanceCollectionFailureFacts(
73
- cause: string,
74
- recovery: string,
75
- requestedBytes = 0,
76
- supportedBytes: number | undefined = undefined,
77
- backend: InstanceBackendKind = 'unknown',
78
- ): InstanceCollectionFailureFacts {
79
- return {
80
- requestedBytes,
81
- supportedBytes,
82
- backend,
83
- owner: 'renderer.instances',
84
- cause,
85
- recovery,
86
- };
87
- }
88
-
89
- /** Detached, bounded collection evidence exposed by Renderer.inspect(). */
90
41
  export interface InstanceCollectionInspection extends InstanceCollectionInfo {
91
42
  readonly residentGeneration: number | undefined;
92
43
  readonly lane: InstanceSubmissionLane;
93
- readonly dirtyRanges: readonly InstanceDirtyRange[];
94
44
  readonly uploadRanges: readonly InstanceDirtyRange[];
95
45
  readonly uploadedBytes: number;
96
46
  readonly requestedBytes: number;
@@ -107,81 +57,46 @@ export interface InstanceCollectionInspection extends InstanceCollectionInfo {
107
57
  | undefined;
108
58
  }
109
59
 
110
- export interface InstanceCollectionCreateInput {
111
- readonly transforms: Float32Array;
112
- }
113
-
114
- export interface InstanceCollectionUpdateInput {
115
- /** Matrix ordinal of the first matrix to replace. */
116
- readonly start: number;
117
- readonly transforms: Float32Array;
118
- }
119
-
120
- export interface InstanceCollectionInvalidDetail {
121
- readonly collectionId?: number;
122
- readonly operation: 'create' | 'replace' | 'update' | 'inspect' | 'release';
123
- readonly expected: string;
124
- readonly actual: number | string;
125
- }
126
-
127
- export type InstanceCollectionErrorCode =
128
- | 'instance-collection-invalid'
129
- | 'instance-collection-not-found'
130
- | 'instance-collection-released';
131
-
132
- export class InstanceCollectionError extends Error {
133
- readonly code: InstanceCollectionErrorCode;
134
- readonly expected: string;
135
- readonly hint: string;
136
- readonly detail: InstanceCollectionInvalidDetail | undefined;
137
- readonly owner = 'renderer.instances' as const;
138
- readonly recovery: string;
139
- readonly facts: InstanceCollectionFailureFacts;
140
-
60
+ export class InstanceTransformsError extends Error {
61
+ readonly code = 'instance-transforms-invalid' as const;
62
+ readonly expected = 'finite column-major mat4 values, with transforms.length a multiple of 16';
63
+ readonly hint = 'repair Instances.transforms in the World or source SceneAsset and retry';
141
64
  constructor(
142
- code: InstanceCollectionErrorCode,
143
- expected: string,
144
- hint: string,
145
- detail?: InstanceCollectionInvalidDetail,
146
- facts?: InstanceCollectionFailureFacts,
65
+ readonly detail: { readonly actualLength: number; readonly nonFiniteIndex?: number },
147
66
  ) {
148
- super(`${code}: ${expected}`);
149
- this.name = 'InstanceCollectionError';
150
- this.code = code;
151
- this.expected = expected;
152
- this.hint = hint;
153
- this.detail = detail;
154
- this.facts =
155
- facts ??
156
- instanceCollectionFailureFacts(
157
- code,
158
- hint,
159
- detail?.operation === 'create' || detail?.operation === 'replace'
160
- ? typeof detail.actual === 'number' && Number.isFinite(detail.actual)
161
- ? detail.actual * Float32Array.BYTES_PER_ELEMENT
162
- : 0
163
- : 0,
164
- );
165
- this.recovery = this.facts.recovery;
67
+ super('Instances.transforms must contain complete finite matrices');
68
+ this.name = 'InstanceTransformsError';
166
69
  }
167
70
  }
71
+ export function validateInstanceTransforms(
72
+ transforms: ArrayLike<number>,
73
+ ): InstanceTransformsError | InstanceTransformsStrideMismatchError | undefined {
74
+ if (transforms.length % MATRIX_STRIDE !== 0)
75
+ return new InstanceTransformsStrideMismatchError(transforms.length);
76
+ for (let index = 0; index < transforms.length; index++) {
77
+ if (!Number.isFinite(transforms[index]))
78
+ return new InstanceTransformsError({
79
+ actualLength: transforms.length,
80
+ nonFiniteIndex: index,
81
+ });
82
+ }
83
+ return undefined;
84
+ }
168
85
 
169
- export type InstanceCollectionResult<T> = Result<T, InstanceCollectionError>;
170
-
171
- interface CollectionRecord {
172
- readonly id: InstanceCollectionId;
173
- transforms: Float32Array;
174
- count: number;
175
- capacity: number;
176
- revision: number;
177
- dirtyRanges: InstanceDirtyRange[];
178
- /** Last revision detached for extraction; repeated reads of that revision
179
- * retain the same ranges for multiple entities sharing one collection. */
180
- lastSnapshotRevision: number;
181
- released: boolean;
86
+ /** A new allocation must receive the complete payload, including after recovery. */
87
+ export function instanceUploadRangesForResident(
88
+ activeIsNew: boolean,
89
+ dirtyRanges: readonly InstanceDirtyRange[],
90
+ fullRange: InstanceDirtyRange,
91
+ ): readonly InstanceDirtyRange[] {
92
+ return activeIsNew ? [fullRange] : dirtyRanges;
182
93
  }
183
94
 
184
- interface CollectionResidency {
95
+ interface Projection extends InstanceCollectionSnapshot {
96
+ readonly world: World;
97
+ readonly entity: number;
98
+ }
99
+ interface Residency {
185
100
  readonly frameNumber: number;
186
101
  readonly residentGeneration: number | undefined;
187
102
  readonly lane: InstanceSubmissionLane;
@@ -193,279 +108,120 @@ interface CollectionResidency {
193
108
  readonly error: InstanceCollectionInspection['error'];
194
109
  }
195
110
 
196
- function nextCapacity(required: number): number {
197
- let capacity = INITIAL_CAPACITY;
198
- while (capacity < required) capacity *= 2;
199
- return capacity;
200
- }
201
-
202
- function invalid(
203
- operation: InstanceCollectionInvalidDetail['operation'],
204
- expected: string,
205
- actual: number | string,
206
- collectionId?: number,
207
- context?: {
208
- readonly requestedBytes?: number;
209
- readonly supportedBytes?: number;
210
- readonly cause?: string;
211
- readonly recovery?: string;
212
- },
213
- ): InstanceCollectionError {
214
- const hint = 'repair the collection payload and retry the same authoring operation';
215
- return new InstanceCollectionError(
216
- 'instance-collection-invalid',
217
- expected,
218
- hint,
219
- { operation, expected, actual, ...(collectionId === undefined ? {} : { collectionId }) },
220
- instanceCollectionFailureFacts(
221
- context?.cause ?? `invalid-${operation}-authoring`,
222
- context?.recovery ?? hint,
223
- context?.requestedBytes ?? 0,
224
- context?.supportedBytes,
225
- ),
226
- );
227
- }
228
-
229
- function validateTransforms(
230
- operation: InstanceCollectionInvalidDetail['operation'],
231
- transforms: Float32Array,
232
- collectionId?: number,
233
- ): InstanceCollectionError | undefined {
234
- if (!(transforms instanceof Float32Array)) {
235
- return invalid(operation, 'transforms is a Float32Array', typeof transforms, collectionId, {
236
- cause: 'invalid-transform-type',
237
- });
238
- }
239
- if (transforms.length % MATRIX_STRIDE !== 0) {
240
- return invalid(
241
- operation,
242
- `transforms.length is a multiple of ${MATRIX_STRIDE}`,
243
- transforms.length,
244
- collectionId,
245
- {
246
- requestedBytes: transforms.byteLength,
247
- cause: 'invalid-transform-stride',
248
- },
249
- );
250
- }
251
- for (const value of transforms) {
252
- if (!Number.isFinite(value)) {
253
- return invalid(operation, 'every transform value is finite', value, collectionId, {
254
- requestedBytes: transforms.byteLength,
255
- cause: 'invalid-transform-value',
256
- });
257
- }
258
- }
259
- return undefined;
260
- }
261
-
262
- function appendRange(ranges: InstanceDirtyRange[], start: number, end: number): void {
263
- if (start >= end) return;
264
- // Updates are allowed to arrive in any order. Insert at the first range
265
- // whose end reaches the new interval, then consume every range that starts
266
- // before the merged end. This preserves the complete union for both
267
- // adjacent and overlapping writes (for example [10, 12) then [8, 11)).
268
- let index = 0;
269
- while (index < ranges.length) {
270
- const existing = ranges[index];
271
- if (existing === undefined || existing.end >= start) break;
272
- index += 1;
273
- }
274
- while (index < ranges.length) {
275
- const existing = ranges[index];
276
- if (existing === undefined || existing.start > end) break;
277
- start = Math.min(start, existing.start);
278
- end = Math.max(end, existing.end);
279
- ranges.splice(index, 1);
280
- }
281
- ranges.splice(index, 0, { start, end });
282
- }
283
-
284
- function appendDirtyRange(record: CollectionRecord, start: number, end: number): void {
285
- appendRange(record.dirtyRanges, start, end);
286
- }
287
-
288
- function missing(
289
- operation: InstanceCollectionInvalidDetail['operation'],
290
- id: InstanceCollectionId,
291
- ): InstanceCollectionError {
292
- return new InstanceCollectionError(
293
- 'instance-collection-not-found',
294
- `instance collection ${Number(id)} is live and owned by this Renderer`,
295
- 'create a collection with renderer.instances.create or retain the original collection id',
296
- { operation, expected: 'a live instance collection id', actual: Number(id), collectionId: id },
297
- );
298
- }
299
-
300
- /**
301
- * Renderer-owned canonical storage for explicit instance transforms.
302
- *
303
- * ECS carries only `Instances.collectionId`; this owner keeps the copied
304
- * matrices, revision and dirty intervals independent of archetype capacity.
305
- * Snapshots are detached before they cross into extraction, so callers cannot
306
- * mutate the canonical source behind the revision protocol.
307
- */
308
- export class InstanceCollectionStore {
111
+ /** Rebuildable renderer projection. All authoring and entity lifetime belong to World. */
112
+ export class InstanceProjectionStore {
309
113
  private nextId = 1;
310
- private epochValue = 0;
311
- private disposed = false;
312
- private readonly records = new Map<InstanceCollectionId, CollectionRecord>();
313
- private readonly residency = new Map<InstanceCollectionId, CollectionResidency>();
314
-
315
- get epoch(): number {
316
- return this.epochValue;
317
- }
318
-
319
- create(input: InstanceCollectionCreateInput): InstanceCollectionResult<InstanceCollectionInfo> {
320
- if (this.disposed) {
321
- return err(
322
- new InstanceCollectionError(
323
- 'instance-collection-released',
324
- 'the Renderer-owned instance collection store is live',
325
- 'create a new Renderer before authoring instance collections',
326
- ),
327
- );
328
- }
329
- const invalidPayload = validateTransforms('create', input.transforms);
330
- if (invalidPayload !== undefined) return err(invalidPayload);
331
- const id = this.nextId++ as InstanceCollectionId;
332
- const count = input.transforms.length / MATRIX_STRIDE;
333
- const record: CollectionRecord = {
334
- id,
335
- transforms: new Float32Array(input.transforms),
114
+ private nextGeneration = 1;
115
+ private identities = new WeakMap<World, Map<number, InstanceCollectionId>>();
116
+ private readonly records = new Map<InstanceCollectionId, Projection>();
117
+ private readonly residency = new Map<InstanceCollectionId, Residency>();
118
+
119
+ project(world: World, entity: number, transforms: ArrayLike<number>): InstanceCollectionSnapshot {
120
+ const collectionId =
121
+ this.identities.get(world)?.get(entity) ?? (this.nextId++ as InstanceCollectionId);
122
+ const previous = this.records.get(collectionId);
123
+ if (
124
+ previous !== undefined &&
125
+ previous.transforms.length === transforms.length &&
126
+ previous.transforms.every((value, index) => Object.is(value, transforms[index]))
127
+ )
128
+ return previous;
129
+ const count = transforms.length / MATRIX_STRIDE;
130
+ // Ordinals are identities within the authored array. Pose edits retain them;
131
+ // resizing seeds topology anew so new instances cannot inherit old motion.
132
+ const generations =
133
+ previous?.count === count
134
+ ? previous.generations
135
+ : Uint32Array.from({ length: count }, () => this.nextGeneration++);
136
+ const record: Projection = {
137
+ collectionId,
138
+ world,
139
+ entity,
140
+ transforms: new Float32Array(transforms),
141
+ generations,
336
142
  count,
337
- capacity: nextCapacity(Math.max(INITIAL_CAPACITY, count)),
338
- revision: 1,
339
- dirtyRanges: count === 0 ? [] : [{ start: 0, end: count }],
340
- lastSnapshotRevision: 0,
341
- released: false,
143
+ revision: (previous?.revision ?? 0) + 1,
342
144
  };
343
- this.records.set(id, record);
344
- this.epochValue += 1;
345
- return ok(this.info(record));
145
+ return record;
346
146
  }
347
147
 
348
- replace(
349
- id: InstanceCollectionId,
350
- transforms: Float32Array,
351
- ): InstanceCollectionResult<InstanceCollectionInfo> {
352
- const record = this.live('replace', id);
353
- if (!record.ok) return record;
354
- const invalidPayload = validateTransforms('replace', transforms, id);
355
- if (invalidPayload !== undefined) return err(invalidPayload);
356
- const count = transforms.length / MATRIX_STRIDE;
357
- record.value.transforms = new Float32Array(transforms);
358
- record.value.count = count;
359
- record.value.capacity = Math.max(record.value.capacity, nextCapacity(Math.max(1, count)));
360
- record.value.revision += 1;
361
- record.value.dirtyRanges = count === 0 ? [] : [{ start: 0, end: count }];
362
- record.value.lastSnapshotRevision = record.value.revision - 1;
363
- this.epochValue += 1;
364
- return ok(this.info(record.value));
148
+ /** Called only after the owning RenderScene accepts its prepared changes. */
149
+ accept(
150
+ world: World,
151
+ entity: number,
152
+ snapshot: {
153
+ readonly collectionId?: InstanceCollectionId;
154
+ readonly revision?: number;
155
+ readonly transforms: Float32Array;
156
+ readonly generations?: Uint32Array;
157
+ },
158
+ ): void {
159
+ const { collectionId, revision, transforms, generations } = snapshot;
160
+ if (collectionId === undefined || revision === undefined || generations === undefined) return;
161
+ let entities = this.identities.get(world);
162
+ if (entities === undefined) {
163
+ entities = new Map();
164
+ this.identities.set(world, entities);
165
+ }
166
+ entities.set(entity, collectionId);
167
+ this.records.set(collectionId, {
168
+ collectionId,
169
+ revision,
170
+ transforms,
171
+ generations,
172
+ count: transforms.length / MATRIX_STRIDE,
173
+ world,
174
+ entity,
175
+ });
365
176
  }
366
177
 
367
- update(
368
- id: InstanceCollectionId,
369
- input: InstanceCollectionUpdateInput,
370
- ): InstanceCollectionResult<InstanceCollectionInfo> {
371
- const record = this.live('update', id);
372
- if (!record.ok) return record;
373
- const invalidPayload = validateTransforms('update', input.transforms, id);
374
- if (invalidPayload !== undefined) return err(invalidPayload);
375
- if (!Number.isInteger(input.start) || input.start < 0) {
376
- return err(
377
- invalid('update', 'start is a non-negative matrix ordinal', input.start, id, {
378
- requestedBytes: input.transforms.byteLength,
379
- supportedBytes: record.value.capacity * MATRIX_STRIDE * Float32Array.BYTES_PER_ELEMENT,
380
- cause: 'invalid-update-range-start',
381
- }),
382
- );
383
- }
384
- const span = input.transforms.length / MATRIX_STRIDE;
385
- const attemptedEnd = input.start + span;
386
- if (attemptedEnd > record.value.count) {
387
- return err(
388
- invalid(
389
- 'update',
390
- `start + matrix count is <= collection count (${record.value.count})`,
391
- attemptedEnd,
392
- id,
393
- {
394
- requestedBytes: attemptedEnd * MATRIX_STRIDE * Float32Array.BYTES_PER_ELEMENT,
395
- supportedBytes: record.value.count * MATRIX_STRIDE * Float32Array.BYTES_PER_ELEMENT,
396
- cause: 'invalid-update-range-end',
397
- },
398
- ),
399
- );
400
- }
401
- if (record.value.lastSnapshotRevision === record.value.revision) {
402
- record.value.dirtyRanges = [];
178
+ release(world: World, entity: number): void {
179
+ const entities = this.identities.get(world);
180
+ const id = entities?.get(entity);
181
+ if (id === undefined) return;
182
+ entities?.delete(entity);
183
+ this.records.delete(id);
184
+ this.residency.delete(id);
185
+ }
186
+ retain(ids: ReadonlySet<InstanceCollectionId>): void {
187
+ for (const record of this.records.values()) {
188
+ if (!ids.has(record.collectionId)) this.release(record.world, record.entity);
403
189
  }
404
- record.value.transforms.set(input.transforms, input.start * MATRIX_STRIDE);
405
- record.value.revision += 1;
406
- appendDirtyRange(record.value, input.start, input.start + span);
407
- this.epochValue += 1;
408
- return ok(this.info(record.value));
409
190
  }
410
-
411
- inspect(id: InstanceCollectionId): InstanceCollectionResult<InstanceCollectionInfo> {
412
- const record = this.live('inspect', id);
413
- return record.ok ? ok(this.info(record.value)) : record;
191
+ dispose(): void {
192
+ this.records.clear();
193
+ this.residency.clear();
194
+ this.identities = new WeakMap();
414
195
  }
415
-
416
- /**
417
- * Return detached residency facts for every live collection.
418
- *
419
- * @internal Record-stage evidence is reported through the two methods below;
420
- * callers only receive immutable PODs and never GPU handles.
421
- */
422
- _inspections(): readonly InstanceCollectionInspection[] {
423
- return Object.freeze(
424
- [...this.records.values()].map((record) => this.projectInspection(record)),
425
- );
196
+ _resetResidency(): void {
197
+ this.residency.clear();
426
198
  }
427
199
 
428
- /** @internal Renderer record owner reports the accepted collection lane. */
429
- _reportResidency(input: {
430
- readonly collectionId: InstanceCollectionId;
431
- readonly frameNumber: number;
432
- readonly residentGeneration: number;
433
- readonly lane: Exclude<InstanceSubmissionLane, 'unresident' | 'unavailable'>;
434
- readonly uploadRanges: readonly InstanceDirtyRange[];
435
- readonly uploadedBytes: number;
436
- readonly requestedBytes: number;
437
- readonly supportedBytes: number | undefined;
438
- readonly backend: InstanceBackendKind;
439
- }): void {
200
+ _reportResidency(
201
+ input: Omit<Residency, 'error' | 'lane'> & {
202
+ readonly collectionId: InstanceCollectionId;
203
+ readonly lane: Exclude<InstanceSubmissionLane, 'unresident' | 'unavailable'>;
204
+ },
205
+ ): void {
440
206
  if (!this.records.has(input.collectionId)) return;
441
207
  const previous = this.residency.get(input.collectionId);
442
- const sameFrame =
443
- previous !== undefined &&
444
- previous.frameNumber === input.frameNumber &&
445
- previous.error === undefined;
446
- const uploadRanges = sameFrame
447
- ? [...previous.uploadRanges].reduce(
448
- (ranges, range) => {
449
- appendRange(ranges, range.start, range.end);
450
- return ranges;
451
- },
452
- input.uploadRanges.map((range) => ({ ...range })),
453
- )
454
- : input.uploadRanges.map((range) => ({ ...range }));
208
+ const sameFrame = previous?.frameNumber === input.frameNumber && previous.error === undefined;
209
+ const ranges = [...(sameFrame ? previous.uploadRanges : []), ...input.uploadRanges]
210
+ .map((range) => ({ ...range }))
211
+ .sort((a, b) => a.start - b.start);
212
+ const uploadRanges: InstanceDirtyRange[] = [];
213
+ for (const range of ranges) {
214
+ const last = uploadRanges.at(-1);
215
+ if (last !== undefined && range.start <= last.end) last.end = Math.max(last.end, range.end);
216
+ else uploadRanges.push(range);
217
+ }
455
218
  this.residency.set(input.collectionId, {
456
- frameNumber: input.frameNumber,
457
- residentGeneration: input.residentGeneration,
458
- lane: input.lane,
219
+ ...input,
459
220
  uploadRanges,
460
- uploadedBytes: sameFrame ? previous.uploadedBytes + input.uploadedBytes : input.uploadedBytes,
461
- requestedBytes: input.requestedBytes,
462
- supportedBytes: input.supportedBytes,
463
- backend: input.backend,
221
+ uploadedBytes: input.uploadedBytes + (sameFrame ? previous.uploadedBytes : 0),
464
222
  error: undefined,
465
223
  });
466
224
  }
467
-
468
- /** @internal Renderer record owner reports a typed admission failure. */
469
225
  _reportFailure(input: {
470
226
  readonly collectionId: InstanceCollectionId;
471
227
  readonly code: InstanceCollectionFailureCode;
@@ -491,121 +247,24 @@ export class InstanceCollectionStore {
491
247
  },
492
248
  });
493
249
  }
494
-
495
- /** @internal A lost device invalidates every renderer-owned GPU resident. */
496
- _resetResidency(): void {
497
- this.residency.clear();
498
- }
499
-
500
- snapshot(id: InstanceCollectionId): InstanceCollectionResult<InstanceCollectionSnapshot> {
501
- const record = this.live('inspect', id);
502
- if (!record.ok) return record;
503
- const value = record.value;
504
- value.lastSnapshotRevision = value.revision;
505
- const result = this.detachedSnapshot(value);
506
- // Keep the current ranges stable for repeated reads by entities sharing
507
- // this collection. The next authoring mutation starts a fresh interval
508
- // set once this revision has been observed.
509
- return ok(result);
510
- }
511
-
512
- /**
513
- * Read a detached matrix view without advancing the render-consumption
514
- * cursor. Inspection and picking may call this between authoring updates;
515
- * the next renderer snapshot must still receive the complete dirty union.
516
- */
517
- peek(id: InstanceCollectionId): InstanceCollectionResult<InstanceCollectionSnapshot> {
518
- const record = this.live('inspect', id);
519
- return record.ok ? ok(this.detachedSnapshot(record.value)) : record;
520
- }
521
-
522
- release(id: InstanceCollectionId): InstanceCollectionResult<void> {
523
- const record = this.records.get(id);
524
- if (record === undefined) return err(missing('release', id));
525
- if (record.released) {
526
- return err(
527
- new InstanceCollectionError(
528
- 'instance-collection-released',
529
- `instance collection ${Number(id)} has not already been released`,
530
- 'do not reuse a released collection id; create a new collection',
531
- {
532
- operation: 'release',
533
- expected: 'a live instance collection id',
534
- actual: Number(id),
535
- collectionId: id,
536
- },
537
- ),
538
- );
539
- }
540
- record.released = true;
541
- this.records.delete(id);
542
- this.residency.delete(id);
543
- this.epochValue += 1;
544
- return ok(undefined);
545
- }
546
-
547
- /** Drop all canonical matrices during Renderer disposal. */
548
- dispose(): void {
549
- if (this.disposed) return;
550
- this.disposed = true;
551
- for (const record of this.records.values()) record.released = true;
552
- this.records.clear();
553
- this.residency.clear();
554
- this.epochValue += 1;
555
- }
556
-
557
- private live(
558
- operation: InstanceCollectionInvalidDetail['operation'],
559
- id: InstanceCollectionId,
560
- ): InstanceCollectionResult<CollectionRecord> {
561
- if (!Number.isInteger(id) || id <= 0) {
562
- return err(invalid(operation, 'collectionId is a positive integer', id, id));
563
- }
564
- if (this.disposed) {
565
- return err(
566
- new InstanceCollectionError(
567
- 'instance-collection-released',
568
- 'the Renderer-owned instance collection store is live',
569
- 'create a new Renderer before using instance collections',
570
- { operation, expected: 'a live collection store', actual: 'disposed', collectionId: id },
571
- ),
572
- );
573
- }
574
- const record = this.records.get(id);
575
- return record === undefined ? err(missing(operation, id)) : ok(record);
576
- }
577
-
578
- private detachedSnapshot(record: CollectionRecord): InstanceCollectionSnapshot {
579
- return {
580
- ...this.info(record),
581
- transforms: new Float32Array(record.transforms),
582
- dirtyRanges: record.dirtyRanges.map((range) => ({ ...range })),
583
- };
584
- }
585
-
586
- private info(record: CollectionRecord): InstanceCollectionInfo {
587
- return Object.freeze({
588
- collectionId: record.id,
589
- count: record.count,
590
- capacity: record.capacity,
591
- revision: record.revision,
592
- });
593
- }
594
-
595
- private projectInspection(record: CollectionRecord): InstanceCollectionInspection {
596
- const residency = this.residency.get(record.id);
597
- return Object.freeze({
598
- ...this.info(record),
599
- residentGeneration: residency?.residentGeneration,
600
- lane: residency?.lane ?? 'unresident',
601
- dirtyRanges: Object.freeze(record.dirtyRanges.map((range) => ({ ...range }))),
602
- uploadRanges: Object.freeze(residency?.uploadRanges.map((range) => ({ ...range })) ?? []),
603
- uploadedBytes: residency?.uploadedBytes ?? 0,
604
- requestedBytes: residency?.requestedBytes ?? record.count * MATRIX_STRIDE * 4,
605
- supportedBytes: residency?.supportedBytes,
606
- backend: residency?.backend ?? 'unknown',
607
- owner: 'renderer.instances',
608
- error: residency?.error,
250
+ _inspections(frameNumber: number): readonly InstanceCollectionInspection[] {
251
+ return [...this.records.values()].map((record) => {
252
+ const resident = this.residency.get(record.collectionId);
253
+ const current = resident?.frameNumber === frameNumber;
254
+ return {
255
+ collectionId: record.collectionId,
256
+ count: record.count,
257
+ revision: record.revision,
258
+ residentGeneration: resident?.residentGeneration,
259
+ lane: resident?.lane ?? 'unresident',
260
+ uploadRanges: current ? resident.uploadRanges.map((range) => ({ ...range })) : [],
261
+ uploadedBytes: current ? resident.uploadedBytes : 0,
262
+ requestedBytes: resident?.requestedBytes ?? record.transforms.byteLength,
263
+ supportedBytes: resident?.supportedBytes,
264
+ backend: resident?.backend ?? 'unknown',
265
+ owner: 'renderer.instances',
266
+ error: resident?.error,
267
+ };
609
268
  });
610
269
  }
611
270
  }