@forgeax/engine-render 0.1.27 → 0.1.29

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 (655) hide show
  1. package/README.md +842 -124
  2. package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
  3. package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
  4. package/dist/assembly/dynamic-geometry-host.d.ts +52 -0
  5. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -0
  6. package/dist/assembly/dynamic-geometry-runtime.d.ts +20 -0
  7. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -0
  8. package/dist/assembly/factory.d.ts +3 -1
  9. package/dist/assembly/factory.d.ts.map +1 -1
  10. package/dist/assembly/gpu-driven-owner.d.ts +10 -0
  11. package/dist/assembly/gpu-driven-owner.d.ts.map +1 -0
  12. package/dist/assembly/host-contract.d.ts +19 -0
  13. package/dist/assembly/host-contract.d.ts.map +1 -1
  14. package/dist/assembly/material/assembly.d.ts +7 -0
  15. package/dist/assembly/material/assembly.d.ts.map +1 -1
  16. package/dist/assembly/material-shader-policy.d.ts +3 -1
  17. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  18. package/dist/assembly/recovery/failure-location.d.ts +12 -0
  19. package/dist/assembly/recovery/failure-location.d.ts.map +1 -0
  20. package/dist/assembly/recovery/renderer-recover.d.ts +6 -4
  21. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  22. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  23. package/dist/assembly/renderer-feature-inspection.d.ts +5 -0
  24. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -0
  25. package/dist/assembly/renderer-frame-transaction.d.ts +19 -0
  26. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  27. package/dist/assembly/renderer-helpers.d.ts +3 -0
  28. package/dist/assembly/renderer-helpers.d.ts.map +1 -1
  29. package/dist/assembly/renderer-inspection.d.ts +4 -0
  30. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  31. package/dist/assembly/shader-prewarm-policy.d.ts +6 -0
  32. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
  33. package/dist/assembly/skin-palette-owner.d.ts +8 -0
  34. package/dist/assembly/skin-palette-owner.d.ts.map +1 -0
  35. package/dist/assembly/ssr-shader-prewarm.d.ts +6 -0
  36. package/dist/assembly/ssr-shader-prewarm.d.ts.map +1 -0
  37. package/dist/assembly/webgpu-device-loss.d.ts +15 -0
  38. package/dist/assembly/webgpu-device-loss.d.ts.map +1 -0
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +38 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -0
  41. package/dist/assembly/webgpu-ready-mipmap.d.ts +11 -0
  42. package/dist/assembly/webgpu-ready-mipmap.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +7 -3
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts +10 -0
  46. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -0
  47. package/dist/assembly/webgpu-renderer-contract.d.ts +62 -0
  48. package/dist/assembly/webgpu-renderer-contract.d.ts.map +1 -0
  49. package/dist/assembly/webgpu-renderer-guards.d.ts +9 -0
  50. package/dist/assembly/webgpu-renderer-guards.d.ts.map +1 -0
  51. package/dist/assembly/webgpu-renderer-observation.d.ts +6 -0
  52. package/dist/assembly/webgpu-renderer-observation.d.ts.map +1 -0
  53. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts +12 -0
  54. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts.map +1 -0
  55. package/dist/assembly/webgpu-renderer.d.ts +7 -141
  56. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  57. package/dist/assembly/webgpu-vertex-layouts.d.ts +28 -84
  58. package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
  59. package/dist/authoring.mjs +3 -3
  60. package/dist/{chunk-ADHHVYLW.mjs → chunk-33XZFTQU.mjs} +245 -39
  61. package/dist/chunk-33XZFTQU.mjs.map +1 -0
  62. package/dist/{chunk-GF523LHF.mjs → chunk-BLXGONR2.mjs} +30 -12
  63. package/dist/chunk-BLXGONR2.mjs.map +1 -0
  64. package/dist/{chunk-KM2NOX2I.mjs → chunk-BQVQOQJH.mjs} +958 -254
  65. package/dist/chunk-BQVQOQJH.mjs.map +1 -0
  66. package/dist/{chunk-HKXTW355.mjs → chunk-BTWH7BP4.mjs} +386 -17
  67. package/dist/chunk-BTWH7BP4.mjs.map +1 -0
  68. package/dist/{chunk-TMIASV2N.mjs → chunk-FUODTTIA.mjs} +3934 -676
  69. package/dist/chunk-FUODTTIA.mjs.map +1 -0
  70. package/dist/{chunk-FJ6P52EE.mjs → chunk-ILQ5MEZF.mjs} +3 -17
  71. package/dist/chunk-ILQ5MEZF.mjs.map +1 -0
  72. package/dist/{chunk-E34VL5VI.mjs → chunk-JQTSEI3Z.mjs} +3 -3
  73. package/dist/{chunk-E34VL5VI.mjs.map → chunk-JQTSEI3Z.mjs.map} +1 -1
  74. package/dist/{chunk-GE3SDD72.mjs → chunk-NICXSHAT.mjs} +16 -38
  75. package/dist/chunk-NICXSHAT.mjs.map +1 -0
  76. package/dist/{chunk-ZZ4YQ474.mjs → chunk-NRNXBLIJ.mjs} +577 -7
  77. package/dist/chunk-NRNXBLIJ.mjs.map +1 -0
  78. package/dist/{chunk-JDWARUOI.mjs → chunk-PA5DRJNI.mjs} +17 -3
  79. package/dist/chunk-PA5DRJNI.mjs.map +1 -0
  80. package/dist/{chunk-XDP6XE5V.mjs → chunk-S4DNKQYQ.mjs} +1118 -446
  81. package/dist/chunk-S4DNKQYQ.mjs.map +1 -0
  82. package/dist/components/camera.d.ts +62 -2
  83. package/dist/components/camera.d.ts.map +1 -1
  84. package/dist/components/index.d.ts +1 -0
  85. package/dist/components/index.d.ts.map +1 -1
  86. package/dist/components/instances.d.ts +6 -20
  87. package/dist/components/instances.d.ts.map +1 -1
  88. package/dist/components/scene-instance.d.ts +2 -1
  89. package/dist/components/scene-instance.d.ts.map +1 -1
  90. package/dist/components/screen-space-reflection.d.ts +14 -0
  91. package/dist/components/screen-space-reflection.d.ts.map +1 -0
  92. package/dist/construct-renderer.mjs +13805 -7186
  93. package/dist/construct-renderer.mjs.map +1 -1
  94. package/dist/device/gpu-residency.d.ts +11 -17
  95. package/dist/device/gpu-residency.d.ts.map +1 -1
  96. package/dist/device/mesh-residency-lifetime.d.ts +21 -0
  97. package/dist/device/mesh-residency-lifetime.d.ts.map +1 -0
  98. package/dist/dynamic-geometry.d.ts +125 -0
  99. package/dist/dynamic-geometry.d.ts.map +1 -0
  100. package/dist/environment/background.d.ts +6 -0
  101. package/dist/environment/background.d.ts.map +1 -0
  102. package/dist/errors/gpu-driven.d.ts +6 -3
  103. package/dist/errors/gpu-driven.d.ts.map +1 -1
  104. package/dist/errors/render.d.ts +7 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/extract/camera.d.ts.map +1 -1
  107. package/dist/extract/gpu-driven.d.ts +33 -3
  108. package/dist/extract/gpu-driven.d.ts.map +1 -1
  109. package/dist/features/host.d.ts +23 -1
  110. package/dist/features/host.d.ts.map +1 -1
  111. package/dist/features/noise-texture.d.ts +17 -0
  112. package/dist/features/noise-texture.d.ts.map +1 -0
  113. package/dist/features/plan.d.ts +83 -2
  114. package/dist/features/plan.d.ts.map +1 -1
  115. package/dist/features/prepared-gpu-work.d.ts +37 -4
  116. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  117. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  118. package/dist/features/prepared-graphics.d.ts +5 -0
  119. package/dist/features/prepared-graphics.d.ts.map +1 -1
  120. package/dist/features/render-graph-compute.d.ts +5 -3
  121. package/dist/features/render-graph-compute.d.ts.map +1 -1
  122. package/dist/features/render-graph-contribution.d.ts +11 -3
  123. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  124. package/dist/features/render-graph-raster.d.ts +19 -3
  125. package/dist/features/render-graph-raster.d.ts.map +1 -1
  126. package/dist/features/types.d.ts +11 -0
  127. package/dist/features/types.d.ts.map +1 -1
  128. package/dist/fullscreen-post-process-pass.d.ts +2 -0
  129. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  130. package/dist/gpu-driven/batch-topology.d.ts +34 -1
  131. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  132. package/dist/gpu-driven/pbr-program.d.ts +10 -0
  133. package/dist/gpu-driven/pbr-program.d.ts.map +1 -0
  134. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  135. package/dist/gpu-driven/production-raster.d.ts +144 -23
  136. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  137. package/dist/gpu-driven/shadow-views.d.ts +126 -0
  138. package/dist/gpu-driven/shadow-views.d.ts.map +1 -0
  139. package/dist/gpu-driven/view-gpu.d.ts +18 -2
  140. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  141. package/dist/gpu-scene-schema.d.ts +2 -8
  142. package/dist/gpu-scene-schema.d.ts.map +1 -1
  143. package/dist/gpu-scene.d.ts +14 -0
  144. package/dist/gpu-scene.d.ts.map +1 -1
  145. package/dist/gpu-texture-usage.d.ts +1 -0
  146. package/dist/gpu-texture-usage.d.ts.map +1 -1
  147. package/dist/hdrp-buffers.d.ts +6 -0
  148. package/dist/hdrp-buffers.d.ts.map +1 -1
  149. package/dist/ibl/frame-resources.d.ts +8 -0
  150. package/dist/ibl/frame-resources.d.ts.map +1 -0
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +21 -8
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +8 -7
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +164 -0
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instances-derived-bounds.d.ts +11 -0
  159. package/dist/instances-derived-bounds.d.ts.map +1 -1
  160. package/dist/instances.d.ts +89 -44
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.d.ts +3 -0
  163. package/dist/internal.d.ts.map +1 -1
  164. package/dist/internal.mjs +118 -10
  165. package/dist/internal.mjs.map +1 -1
  166. package/dist/lifecycle.d.ts +2 -1
  167. package/dist/lifecycle.d.ts.map +1 -1
  168. package/dist/material-row.d.ts +5 -0
  169. package/dist/material-row.d.ts.map +1 -0
  170. package/dist/materials.d.ts +15 -0
  171. package/dist/materials.d.ts.map +1 -1
  172. package/dist/pbr-pipeline.d.ts +21 -5
  173. package/dist/pbr-pipeline.d.ts.map +1 -1
  174. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  175. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts +12 -0
  176. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts.map +1 -0
  177. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts +70 -0
  178. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts.map +1 -0
  179. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts +75 -0
  180. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts.map +1 -0
  181. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts +111 -0
  182. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts.map +1 -0
  183. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts +16 -0
  184. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts.map +1 -0
  185. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts +14 -0
  186. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts.map +1 -0
  187. package/dist/pipeline/standard-output/auto-exposure/state.d.ts +46 -0
  188. package/dist/pipeline/standard-output/auto-exposure/state.d.ts.map +1 -0
  189. package/dist/pipeline/standard-output/color-transform.d.ts +27 -0
  190. package/dist/pipeline/standard-output/color-transform.d.ts.map +1 -0
  191. package/dist/pipeline/standard-output/graph.d.ts +15 -0
  192. package/dist/pipeline/standard-output/graph.d.ts.map +1 -0
  193. package/dist/pipeline/standard-output/lut-admission.d.ts +29 -0
  194. package/dist/pipeline/standard-output/lut-admission.d.ts.map +1 -0
  195. package/dist/pipeline/standard-output/lut-gpu.d.ts +48 -0
  196. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -0
  197. package/dist/pipeline/standard-output/lut-state.d.ts +68 -0
  198. package/dist/pipeline/standard-output/lut-state.d.ts.map +1 -0
  199. package/dist/pipeline/standard-output/resources.d.ts +10 -0
  200. package/dist/pipeline/standard-output/resources.d.ts.map +1 -0
  201. package/dist/pipeline/standard-output/types.d.ts +39 -0
  202. package/dist/pipeline/standard-output/types.d.ts.map +1 -0
  203. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  204. package/dist/pipeline/standard-post.d.ts +2 -2
  205. package/dist/pipeline/standard-post.d.ts.map +1 -1
  206. package/dist/pipeline-builder.d.ts +2 -1
  207. package/dist/pipeline-builder.d.ts.map +1 -1
  208. package/dist/pipeline-spec-types.d.ts +4 -0
  209. package/dist/pipeline-spec-types.d.ts.map +1 -1
  210. package/dist/pipeline-spec.d.ts +1 -9
  211. package/dist/pipeline-spec.d.ts.map +1 -1
  212. package/dist/points-lines/standard-owner.d.ts +1 -1
  213. package/dist/points-lines/standard-owner.d.ts.map +1 -1
  214. package/dist/prepare/prepared-graphics-resolver.d.ts +6 -1
  215. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  216. package/dist/record/dynamic-geometry-consumption.d.ts +15 -0
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -0
  218. package/dist/record/frame-lighting.d.ts +3 -3
  219. package/dist/record/frame-lighting.d.ts.map +1 -1
  220. package/dist/record/frame-snapshot.d.ts +106 -5
  221. package/dist/record/frame-snapshot.d.ts.map +1 -1
  222. package/dist/record/frame-targets.d.ts.map +1 -1
  223. package/dist/record/frame.d.ts +39 -4
  224. package/dist/record/frame.d.ts.map +1 -1
  225. package/dist/record/main-pass-geometry.d.ts +7 -8
  226. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  227. package/dist/record/main-pass-material.d.ts +38 -1
  228. package/dist/record/main-pass-material.d.ts.map +1 -1
  229. package/dist/record/main-pass-sprite-draws.d.ts +2 -10
  230. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  231. package/dist/record/main-pass.d.ts +12 -2
  232. package/dist/record/main-pass.d.ts.map +1 -1
  233. package/dist/record/mesh-ssbo.d.ts +15 -6
  234. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  235. package/dist/record/prepared-material-bindings.d.ts +19 -0
  236. package/dist/record/prepared-material-bindings.d.ts.map +1 -0
  237. package/dist/record/recovery-pipeline.d.ts +2 -9
  238. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  239. package/dist/record/render-context.d.ts +76 -26
  240. package/dist/record/render-context.d.ts.map +1 -1
  241. package/dist/record/shadow-pass.d.ts +62 -7
  242. package/dist/record/shadow-pass.d.ts.map +1 -1
  243. package/dist/record/skybox-post-pass.d.ts +1 -1
  244. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  245. package/dist/record/typed-frame-graph.d.ts +35 -7
  246. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  247. package/dist/record/view-ubo.d.ts +1 -0
  248. package/dist/record/view-ubo.d.ts.map +1 -1
  249. package/dist/recovery/render-system-candidate.d.ts +10 -2
  250. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  251. package/dist/recovery/render-system-roots.d.ts +11 -0
  252. package/dist/recovery/render-system-roots.d.ts.map +1 -0
  253. package/dist/recovery/types.d.ts +76 -0
  254. package/dist/recovery/types.d.ts.map +1 -0
  255. package/dist/reflection/record-owner.d.ts +0 -2
  256. package/dist/reflection/record-owner.d.ts.map +1 -1
  257. package/dist/render-contract.d.ts +185 -30
  258. package/dist/render-contract.d.ts.map +1 -1
  259. package/dist/render-graph-primitives.d.ts +1 -0
  260. package/dist/render-graph-primitives.d.ts.map +1 -1
  261. package/dist/render-pipeline.d.ts +64 -5
  262. package/dist/render-pipeline.d.ts.map +1 -1
  263. package/dist/render-system-extract-tail.d.ts +7 -5
  264. package/dist/render-system-extract-tail.d.ts.map +1 -1
  265. package/dist/render-system-extract.d.ts +101 -41
  266. package/dist/render-system-extract.d.ts.map +1 -1
  267. package/dist/render-system-projections.d.ts +22 -0
  268. package/dist/render-system-projections.d.ts.map +1 -0
  269. package/dist/render-system.d.ts +34 -77
  270. package/dist/render-system.d.ts.map +1 -1
  271. package/dist/scene/render-scene-types.d.ts +14 -7
  272. package/dist/scene/render-scene-types.d.ts.map +1 -1
  273. package/dist/scene/render-scene.d.ts +29 -11
  274. package/dist/scene/render-scene.d.ts.map +1 -1
  275. package/dist/scene/shadow-visibility.d.ts +5 -0
  276. package/dist/scene/shadow-visibility.d.ts.map +1 -0
  277. package/dist/ssr/admission.d.ts +70 -1
  278. package/dist/ssr/admission.d.ts.map +1 -1
  279. package/dist/ssr/compose.d.ts +13 -0
  280. package/dist/ssr/compose.d.ts.map +1 -0
  281. package/dist/ssr/errors.d.ts +35 -0
  282. package/dist/ssr/errors.d.ts.map +1 -1
  283. package/dist/ssr/graph.d.ts +60 -0
  284. package/dist/ssr/graph.d.ts.map +1 -0
  285. package/dist/ssr/history.d.ts +97 -0
  286. package/dist/ssr/history.d.ts.map +1 -0
  287. package/dist/ssr/hiz.d.ts +37 -0
  288. package/dist/ssr/hiz.d.ts.map +1 -0
  289. package/dist/ssr/inspection.d.ts +42 -0
  290. package/dist/ssr/inspection.d.ts.map +1 -0
  291. package/dist/ssr/resources.d.ts +58 -0
  292. package/dist/ssr/resources.d.ts.map +1 -0
  293. package/dist/ssr/temporal.d.ts +38 -0
  294. package/dist/ssr/temporal.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts +32 -10
  296. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  297. package/dist/systems/skin-palette-types.d.ts +15 -0
  298. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  299. package/dist/systems/transparent-dispatch.d.ts +9 -0
  300. package/dist/systems/transparent-dispatch.d.ts.map +1 -0
  301. package/dist/targets/material-source.d.ts +7 -0
  302. package/dist/targets/material-source.d.ts.map +1 -1
  303. package/dist/temporal/frame-coordinator.d.ts +7 -0
  304. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  305. package/dist/temporal/gpu.d.ts +8 -0
  306. package/dist/temporal/gpu.d.ts.map +1 -1
  307. package/dist/temporal/history.d.ts.map +1 -1
  308. package/dist/temporal/index.mjs +6 -6
  309. package/dist/temporal/inspection.d.ts.map +1 -1
  310. package/dist/temporal/standard-scene-data.d.ts +2 -1
  311. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  312. package/dist/temporal/temporal-view.d.ts +2 -0
  313. package/dist/temporal/temporal-view.d.ts.map +1 -1
  314. package/dist/typed-render-graph-primitives.d.ts +35 -1
  315. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  316. package/dist/typed-shadow-passes.d.ts +3 -1
  317. package/dist/typed-shadow-passes.d.ts.map +1 -1
  318. package/dist/volume/temporal.d.ts +6 -0
  319. package/dist/volume/temporal.d.ts.map +1 -1
  320. package/package.json +21 -20
  321. package/src/__tests__/auto-exposure-gpu-evidence.ts +291 -0
  322. package/src/__tests__/auto-exposure-inspection.unit.test.ts +80 -0
  323. package/src/__tests__/auto-exposure-transaction.integration.test.ts +99 -0
  324. package/src/__tests__/auto-exposure.browser.test.ts +33 -0
  325. package/src/__tests__/auto-exposure.dawn.test.ts +33 -0
  326. package/src/__tests__/detached-inspection.integration.test.ts +5 -0
  327. package/src/__tests__/device-scope-lifecycle.unit.test.ts +18 -0
  328. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +18 -0
  329. package/src/__tests__/docs-gate-green.unit.test.ts +3 -3
  330. package/src/__tests__/dynamic-geometry-host.unit.test.ts +1123 -0
  331. package/src/__tests__/dynamic-geometry.unit.test.ts +233 -0
  332. package/src/__tests__/factory-contract.integration.test.ts +73 -22
  333. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +19 -0
  334. package/src/__tests__/feature-depth-input.dawn.test.ts +121 -0
  335. package/src/__tests__/feature-noise.unit.test.ts +38 -0
  336. package/src/__tests__/fixtures/taa-resolve-pinned-baseline.wgsl +301 -0
  337. package/src/__tests__/frame-camera-selection.unit.test.ts +131 -0
  338. package/src/__tests__/frame-plan-contract.unit.test.ts +24 -0
  339. package/src/__tests__/frame-targets.unit.test.ts +24 -0
  340. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +3 -0
  341. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +79 -0
  342. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +287 -6
  343. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +122 -142
  344. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +10 -1
  345. package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +264 -0
  346. package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +349 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1417 -0
  348. package/src/__tests__/gpu-driven-pbr.integration.test.ts +21 -0
  349. package/src/__tests__/gpu-driven-production-fixture.ts +96 -0
  350. package/src/__tests__/gpu-driven-production.integration.test.ts +1075 -93
  351. package/src/__tests__/gpu-driven-scaling.unit.test.ts +1 -3
  352. package/src/__tests__/gpu-driven-shadow-views.browser.test.ts +63 -0
  353. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +294 -0
  354. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +97 -0
  355. package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +168 -0
  356. package/src/__tests__/gpu-driven-skin-contract.test-d.ts +11 -0
  357. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +72 -20
  358. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +30 -9
  359. package/src/__tests__/gpu-driven-view.unit.test.ts +159 -52
  360. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -1
  361. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +42 -0
  362. package/src/__tests__/gpu-scene-render-graph-gpu.ts +19 -5
  363. package/src/__tests__/gpu-scene.dawn.test.ts +40 -13
  364. package/src/__tests__/gpu-scene.unit.test.ts +559 -33
  365. package/src/__tests__/instances-culling.integration.test.ts +36 -10
  366. package/src/__tests__/instances-derived-bounds.unit.test.ts +54 -0
  367. package/src/__tests__/instances-store.unit.test.ts +242 -39
  368. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +6 -0
  369. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +13 -16
  370. package/src/__tests__/lut-lkg-transaction.integration.test.ts +122 -0
  371. package/src/__tests__/material-contract-inventory.unit.test.ts +5 -6
  372. package/src/__tests__/material-dispatch-shader-id.unit.test.ts +51 -0
  373. package/src/__tests__/material-lane-selection.unit.test.ts +60 -0
  374. package/src/__tests__/material-numeric-upload.unit.test.ts +53 -0
  375. package/src/__tests__/material-texture-handles.unit.test.ts +18 -0
  376. package/src/__tests__/material-texture-source.unit.test.ts +87 -0
  377. package/src/__tests__/materials-authoring-validation.unit.test.ts +41 -0
  378. package/src/__tests__/materials-standard-contract.unit.test.ts +52 -2
  379. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
  380. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +53 -0
  381. package/src/__tests__/normal-fallback.dawn.test.ts +122 -0
  382. package/src/__tests__/particle-material-input-layout.unit.test.ts +104 -0
  383. package/src/__tests__/physical-clearcoat.integration.test.ts +37 -3
  384. package/src/__tests__/pipeline-texture-specialization.unit.test.ts +138 -0
  385. package/src/__tests__/point-shadow-inspection.unit.test.ts +2 -0
  386. package/src/__tests__/prepared-gpu-driven-pbr-contract.test-d.ts +31 -0
  387. package/src/__tests__/prepared-gpu-driven-pbr-contract.unit.test.ts +39 -0
  388. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +35 -4
  389. package/src/__tests__/prepared-graphics-capability.unit.test.ts +21 -0
  390. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +6 -2
  391. package/src/__tests__/profiler-phase-catalog.test.ts +5 -0
  392. package/src/__tests__/public-surface.test-d.ts +3 -0
  393. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +30 -12
  394. package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +104 -0
  395. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +2 -1
  396. package/src/__tests__/render-error-code-owner.test-d.ts +4 -0
  397. package/src/__tests__/render-error-detail-ssot.test-d.ts +22 -0
  398. package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
  399. package/src/__tests__/render-feature-gpu-work.integration.test.ts +285 -2
  400. package/src/__tests__/render-feature-plan.unit.test.ts +245 -0
  401. package/src/__tests__/render-feature-shadow-order.unit.test.ts +228 -0
  402. package/src/__tests__/render-feature-zero-work.unit.test.ts +35 -1
  403. package/src/__tests__/render-graph-fallback.integration.test.ts +2 -2
  404. package/src/__tests__/render-owner-cohesion.unit.test.ts +55 -0
  405. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +426 -0
  406. package/src/__tests__/render-scene-projection.unit.test.ts +914 -23
  407. package/src/__tests__/render-scene-resource-updates.integration.test.ts +214 -0
  408. package/src/__tests__/render-scene-skin-lifecycle.integration.test.ts +173 -0
  409. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +133 -0
  410. package/src/__tests__/render-target-material-source.test-d.ts +27 -3
  411. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +61 -1
  412. package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
  413. package/src/__tests__/shader-manifest-fixture.ts +39 -0
  414. package/src/__tests__/skin-motion-regression.unit.test.ts +0 -33
  415. package/src/__tests__/skin-palette-persistent.integration.test.ts +28 -0
  416. package/src/__tests__/skin-palette-persistent.unit.test.ts +247 -0
  417. package/src/__tests__/skinned-shadow-caster.test.ts +118 -14
  418. package/src/__tests__/specular-environment-scale.dawn.test.ts +156 -0
  419. package/src/__tests__/ssr-admission-matrix.integration.test.ts +7 -1
  420. package/src/__tests__/ssr-confidence-compose.unit.test.ts +84 -0
  421. package/src/__tests__/ssr-coordinate-oracle.unit.test.ts +28 -0
  422. package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
  423. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +91 -0
  424. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +112 -0
  425. package/src/__tests__/ssr-gpu-dispatch.ts +946 -0
  426. package/src/__tests__/ssr-graph-topology.unit.test.ts +104 -0
  427. package/src/__tests__/ssr-history-filter.dawn.test.ts +198 -0
  428. package/src/__tests__/ssr-hit-color.dawn.test.ts +273 -0
  429. package/src/__tests__/ssr-hiz-odd-reduction.dawn.test.ts +569 -0
  430. package/src/__tests__/ssr-hiz-rescue.dawn.test.ts +279 -0
  431. package/src/__tests__/ssr-hiz.browser.test.ts +150 -0
  432. package/src/__tests__/ssr-hiz.dawn.test.ts +150 -0
  433. package/src/__tests__/ssr-hiz.unit.test.ts +56 -0
  434. package/src/__tests__/ssr-inspection.unit.test.ts +105 -0
  435. package/src/__tests__/ssr-memory-budget.unit.test.ts +45 -0
  436. package/src/__tests__/ssr-performance-sequence-aggregation.unit.test.ts +15 -0
  437. package/src/__tests__/ssr-public-surface.test-d.ts +37 -0
  438. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +387 -0
  439. package/src/__tests__/ssr-reflection-mip-reducer.dawn.test.ts +309 -0
  440. package/src/__tests__/ssr-reprojection-probe.ts +90 -0
  441. package/src/__tests__/ssr-roughness-mip.dawn.test.ts +163 -0
  442. package/src/__tests__/ssr-shader-prewarm.unit.test.ts +59 -0
  443. package/src/__tests__/ssr-spatial.integration.test.ts +141 -0
  444. package/src/__tests__/ssr-stable-lattice.dawn.test.ts +475 -0
  445. package/src/__tests__/ssr-temporal-history.unit.test.ts +202 -0
  446. package/src/__tests__/ssr-texel-crossing.dawn.test.ts +448 -0
  447. package/src/__tests__/ssr-zero-work.integration.test.ts +87 -0
  448. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +44 -12
  449. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +29 -0
  450. package/src/__tests__/standard-output-chain-contract.unit.test.ts +99 -0
  451. package/src/__tests__/standard-output-chain.integration.test.ts +73 -0
  452. package/src/__tests__/standard-output-gpu-evidence.ts +205 -0
  453. package/src/__tests__/standard-output.browser.test.ts +15 -0
  454. package/src/__tests__/standard-output.dawn.test.ts +15 -0
  455. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +38 -0
  456. package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
  457. package/src/__tests__/standard-profile-oracle.unit.test.ts +22 -0
  458. package/src/__tests__/standard-surface-lighting.unit.test.ts +41 -0
  459. package/src/__tests__/standard-texture-specialization.dawn.test.ts +141 -0
  460. package/src/__tests__/surface-adjacent-regressions.integration.test.ts +6 -3
  461. package/src/__tests__/taa-coverage-edge.dawn.test.ts +193 -0
  462. package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
  463. package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +778 -0
  464. package/src/__tests__/taa-stability-feedback.browser.test.ts +23 -0
  465. package/src/__tests__/taa-stability-feedback.dawn.test.ts +68 -0
  466. package/src/__tests__/taa-stability-feedback.ts +341 -0
  467. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +49 -7
  468. package/src/__tests__/temporal-reset-matrix.unit.test.ts +9 -0
  469. package/src/__tests__/temporal-transaction.integration.test.ts +28 -0
  470. package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
  471. package/src/__tests__/typed-pipeline-topology.unit.test.ts +109 -4
  472. package/src/__tests__/typed-scene-pass-material-cache.integration.test.ts +126 -0
  473. package/src/__tests__/vertex-layouts-ssot.unit.test.ts +47 -0
  474. package/src/__tests__/visibility-extract.perf.test.ts +20 -8
  475. package/src/__tests__/visibility-instances.integration.test.ts +19 -7
  476. package/src/__tests__/visibility-producer-matrix.integration.test.ts +20 -9
  477. package/src/assembly/atmosphere-shader-prewarm.ts +38 -0
  478. package/src/assembly/dynamic-geometry-host.ts +887 -0
  479. package/src/assembly/dynamic-geometry-runtime.ts +71 -0
  480. package/src/assembly/factory.ts +4 -0
  481. package/src/assembly/gpu-driven-owner.ts +29 -0
  482. package/src/assembly/host-contract.ts +36 -0
  483. package/src/assembly/material/assembly.ts +38 -0
  484. package/src/assembly/material-shader-policy.ts +71 -28
  485. package/src/assembly/recovery/failure-location.ts +62 -0
  486. package/src/assembly/recovery/renderer-recover.ts +19 -17
  487. package/src/assembly/renderer-facade.ts +29 -0
  488. package/src/assembly/renderer-feature-inspection.ts +13 -0
  489. package/src/assembly/renderer-frame-transaction.ts +63 -0
  490. package/src/assembly/renderer-helpers.ts +26 -0
  491. package/src/assembly/renderer-inspection.ts +6 -0
  492. package/src/assembly/shader-prewarm-policy.ts +32 -0
  493. package/src/assembly/skin-palette-owner.ts +21 -0
  494. package/src/assembly/ssr-shader-prewarm.ts +41 -0
  495. package/src/assembly/webgpu-device-loss.ts +75 -0
  496. package/src/assembly/webgpu-pbr-ready.ts +232 -0
  497. package/src/assembly/webgpu-ready-mipmap.ts +26 -0
  498. package/src/assembly/webgpu-ready.ts +142 -121
  499. package/src/assembly/webgpu-renderer-bootstrap.ts +85 -0
  500. package/src/assembly/webgpu-renderer-contract.ts +69 -0
  501. package/src/assembly/webgpu-renderer-guards.ts +32 -0
  502. package/src/assembly/webgpu-renderer-observation.ts +43 -0
  503. package/src/assembly/webgpu-renderer-recovery-failure.ts +62 -0
  504. package/src/assembly/webgpu-renderer.ts +675 -614
  505. package/src/assembly/webgpu-vertex-layouts.ts +233 -87
  506. package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
  507. package/src/components/camera.ts +287 -7
  508. package/src/components/index.ts +1 -0
  509. package/src/components/instances.ts +45 -18
  510. package/src/components/scene-instance.ts +2 -1
  511. package/src/components/screen-space-reflection.ts +21 -0
  512. package/src/components/sprite-animation.ts +3 -3
  513. package/src/components/sprite-instances.ts +1 -1
  514. package/src/device/gpu-residency.ts +96 -93
  515. package/src/device/mesh-residency-lifetime.ts +73 -0
  516. package/src/dynamic-geometry.ts +736 -0
  517. package/src/environment/background.ts +263 -0
  518. package/src/errors/gpu-driven.ts +39 -5
  519. package/src/errors/render.ts +27 -3
  520. package/src/extract/camera.ts +26 -1
  521. package/src/extract/gpu-driven.ts +185 -10
  522. package/src/features/host.ts +237 -19
  523. package/src/features/noise-texture.ts +91 -0
  524. package/src/features/plan.ts +553 -24
  525. package/src/features/prepared-gpu-work.ts +631 -49
  526. package/src/features/prepared-graphics-store.ts +31 -0
  527. package/src/features/prepared-graphics.ts +5 -0
  528. package/src/features/render-graph-compute.ts +41 -8
  529. package/src/features/render-graph-contribution.ts +141 -3
  530. package/src/features/render-graph-raster.ts +143 -30
  531. package/src/features/types.ts +11 -0
  532. package/src/fullscreen-post-process-pass.ts +3 -0
  533. package/src/gpu-driven/batch-topology.ts +424 -102
  534. package/src/gpu-driven/pbr-program.ts +31 -0
  535. package/src/gpu-driven/prepared-draw.ts +29 -4
  536. package/src/gpu-driven/production-raster.ts +2267 -694
  537. package/src/gpu-driven/shadow-views.ts +539 -0
  538. package/src/gpu-driven/view-gpu.ts +188 -41
  539. package/src/gpu-scene-schema.ts +52 -11
  540. package/src/gpu-scene.ts +186 -99
  541. package/src/gpu-texture-usage.ts +1 -0
  542. package/src/hdrp-buffers.ts +72 -36
  543. package/src/ibl/frame-resources.ts +38 -0
  544. package/src/ibl/skylight-bind-group.ts +5 -4
  545. package/src/index.ts +125 -1
  546. package/src/inspection-types.ts +191 -0
  547. package/src/instances-derived-bounds.ts +258 -34
  548. package/src/instances.ts +459 -150
  549. package/src/internal.ts +22 -0
  550. package/src/lifecycle.ts +2 -0
  551. package/src/material-row.ts +145 -0
  552. package/src/materials.ts +44 -8
  553. package/src/pbr-pipeline.ts +159 -17
  554. package/src/pipeline/standard-forward-lane.ts +52 -24
  555. package/src/pipeline/standard-output/__tests__/lut-admission.unit.test.ts +103 -0
  556. package/src/pipeline/standard-output/auto-exposure/__tests__/capability.unit.test.ts +40 -0
  557. package/src/pipeline/standard-output/auto-exposure/__tests__/gpu.contract.unit.test.ts +125 -0
  558. package/src/pipeline/standard-output/auto-exposure/__tests__/graph.contract.unit.test.ts +94 -0
  559. package/src/pipeline/standard-output/auto-exposure/__tests__/oracle.test.ts +108 -0
  560. package/src/pipeline/standard-output/auto-exposure/__tests__/preset.test.ts +26 -0
  561. package/src/pipeline/standard-output/auto-exposure/capability.ts +38 -0
  562. package/src/pipeline/standard-output/auto-exposure/gpu.ts +567 -0
  563. package/src/pipeline/standard-output/auto-exposure/graph.ts +221 -0
  564. package/src/pipeline/standard-output/auto-exposure/inspection.ts +231 -0
  565. package/src/pipeline/standard-output/auto-exposure/oracle.ts +291 -0
  566. package/src/pipeline/standard-output/auto-exposure/preset.ts +28 -0
  567. package/src/pipeline/standard-output/auto-exposure/state.ts +156 -0
  568. package/src/pipeline/standard-output/color-transform.ts +124 -0
  569. package/src/pipeline/standard-output/graph.ts +139 -0
  570. package/src/pipeline/standard-output/lut-admission.ts +121 -0
  571. package/src/pipeline/standard-output/lut-gpu.ts +399 -0
  572. package/src/pipeline/standard-output/lut-state.ts +176 -0
  573. package/src/pipeline/standard-output/resources.ts +121 -0
  574. package/src/pipeline/standard-output/types.ts +58 -0
  575. package/src/pipeline/standard-pipeline.ts +192 -59
  576. package/src/pipeline/standard-post.ts +186 -27
  577. package/src/pipeline-builder.ts +16 -6
  578. package/src/pipeline-spec-types.ts +4 -0
  579. package/src/pipeline-spec.ts +37 -29
  580. package/src/points-lines/standard-owner.ts +6 -14
  581. package/src/prepare/prepared-graphics-resolver.ts +9 -2
  582. package/src/record/__tests__/material-slot-plan.unit.test.ts +48 -0
  583. package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
  584. package/src/record/__tests__/recovery-pipeline.unit.test.ts +2 -29
  585. package/src/record/__tests__/sprite-material-abi.unit.test.ts +36 -5
  586. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +45 -0
  587. package/src/record/__tests__/view-ubo-layout.unit.test.ts +5 -0
  588. package/src/record/dynamic-geometry-consumption.ts +59 -0
  589. package/src/record/frame-lighting.ts +12 -11
  590. package/src/record/frame-snapshot.ts +133 -23
  591. package/src/record/frame-targets.ts +9 -0
  592. package/src/record/frame.ts +727 -133
  593. package/src/record/main-pass-geometry.ts +162 -98
  594. package/src/record/main-pass-material.ts +115 -26
  595. package/src/record/main-pass-sprite-draws.ts +18 -107
  596. package/src/record/main-pass.ts +78 -8
  597. package/src/record/material-uniforms.ts +1 -1
  598. package/src/record/mesh-ssbo.ts +59 -15
  599. package/src/record/prepared-material-bindings.ts +234 -0
  600. package/src/record/recovery-pipeline.ts +59 -136
  601. package/src/record/render-context.ts +92 -22
  602. package/src/record/shadow-pass.ts +1231 -209
  603. package/src/record/skybox-post-pass.ts +14 -3
  604. package/src/record/typed-frame-graph.ts +1006 -53
  605. package/src/record/view-ubo.ts +11 -0
  606. package/src/recovery/render-system-candidate.ts +90 -66
  607. package/src/recovery/render-system-roots.ts +113 -0
  608. package/src/recovery/types.ts +77 -0
  609. package/src/reflection/record-owner.ts +26 -54
  610. package/src/render-contract.ts +219 -25
  611. package/src/render-graph-primitives.ts +6 -2
  612. package/src/render-pipeline.ts +70 -1
  613. package/src/render-system-extract-tail.ts +409 -160
  614. package/src/render-system-extract.ts +376 -102
  615. package/src/render-system-projections.ts +241 -0
  616. package/src/render-system.ts +692 -791
  617. package/src/scene/render-scene-types.ts +13 -4
  618. package/src/scene/render-scene.ts +569 -355
  619. package/src/scene/shadow-visibility.ts +21 -0
  620. package/src/ssr/admission.ts +380 -14
  621. package/src/ssr/compose.ts +144 -0
  622. package/src/ssr/errors.ts +48 -0
  623. package/src/ssr/graph.ts +777 -0
  624. package/src/ssr/history.ts +436 -0
  625. package/src/ssr/hiz.ts +124 -0
  626. package/src/ssr/inspection.ts +124 -0
  627. package/src/ssr/resources.ts +202 -0
  628. package/src/ssr/temporal.ts +164 -0
  629. package/src/systems/skin-palette-allocator.ts +495 -148
  630. package/src/systems/skin-palette-types.ts +17 -0
  631. package/src/systems/transparent-dispatch.ts +90 -0
  632. package/src/targets/material-source.ts +34 -0
  633. package/src/temporal/coverage.ts +1 -1
  634. package/src/temporal/frame-coordinator.ts +23 -2
  635. package/src/temporal/gpu.ts +74 -12
  636. package/src/temporal/history.ts +3 -1
  637. package/src/temporal/inspection.ts +2 -1
  638. package/src/temporal/standard-scene-data.ts +3 -1
  639. package/src/temporal/temporal-view.ts +3 -0
  640. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +204 -139
  641. package/src/typed-render-graph-primitives.ts +266 -74
  642. package/src/typed-shadow-passes.ts +122 -12
  643. package/src/volume/temporal.ts +10 -0
  644. package/dist/chunk-ADHHVYLW.mjs.map +0 -1
  645. package/dist/chunk-FJ6P52EE.mjs.map +0 -1
  646. package/dist/chunk-GE3SDD72.mjs.map +0 -1
  647. package/dist/chunk-GF523LHF.mjs.map +0 -1
  648. package/dist/chunk-HKXTW355.mjs.map +0 -1
  649. package/dist/chunk-JDWARUOI.mjs.map +0 -1
  650. package/dist/chunk-KM2NOX2I.mjs.map +0 -1
  651. package/dist/chunk-TMIASV2N.mjs.map +0 -1
  652. package/dist/chunk-XDP6XE5V.mjs.map +0 -1
  653. package/dist/chunk-ZZ4YQ474.mjs.map +0 -1
  654. package/src/__tests__/instances-world-ownership.integration.test.ts +0 -62
  655. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +0 -36
package/src/instances.ts CHANGED
@@ -1,25 +1,47 @@
1
- import type { World } from '@forgeax/engine-ecs';
2
1
  import type { RhiErrorCode } from '@forgeax/engine-rhi';
2
+ import { err, ok, type Result } from '@forgeax/engine-types';
3
3
 
4
4
  const MATRIX_STRIDE = 16;
5
+ const INITIAL_CAPACITY = 1;
5
6
 
6
7
  export type InstanceCollectionId = number & {
7
8
  readonly __forgeaxInstanceCollectionId: unique symbol;
8
9
  };
9
10
 
10
- export interface InstanceCollectionInfo {
11
+ export interface InstanceCollectionData {
11
12
  readonly collectionId: InstanceCollectionId;
13
+ }
14
+
15
+ export interface InstanceCollectionInfo extends InstanceCollectionData {
12
16
  readonly count: number;
17
+ readonly capacity: number;
13
18
  readonly revision: number;
14
19
  }
15
20
 
16
- export interface InstanceUploadRange {
21
+ export interface InstanceDirtyRange {
17
22
  start: number;
18
23
  end: number;
19
24
  }
20
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
+
21
42
  export interface InstanceCollectionSnapshot extends InstanceCollectionInfo {
22
43
  readonly transforms: Float32Array;
44
+ readonly dirtyRanges: readonly InstanceDirtyRange[];
23
45
  }
24
46
 
25
47
  /** The renderer-owned submission lane selected for one collection. */
@@ -47,11 +69,29 @@ export interface InstanceCollectionFailureFacts {
47
69
  readonly recovery: string;
48
70
  }
49
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
+
50
89
  /** Detached, bounded collection evidence exposed by Renderer.inspect(). */
51
90
  export interface InstanceCollectionInspection extends InstanceCollectionInfo {
52
91
  readonly residentGeneration: number | undefined;
53
92
  readonly lane: InstanceSubmissionLane;
54
- readonly uploadRanges: readonly InstanceUploadRange[];
93
+ readonly dirtyRanges: readonly InstanceDirtyRange[];
94
+ readonly uploadRanges: readonly InstanceDirtyRange[];
55
95
  readonly uploadedBytes: number;
56
96
  readonly requestedBytes: number;
57
97
  readonly supportedBytes: number | undefined;
@@ -67,11 +107,85 @@ export interface InstanceCollectionInspection extends InstanceCollectionInfo {
67
107
  | undefined;
68
108
  }
69
109
 
70
- export interface InstanceResidency {
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
+
141
+ constructor(
142
+ code: InstanceCollectionErrorCode,
143
+ expected: string,
144
+ hint: string,
145
+ detail?: InstanceCollectionInvalidDetail,
146
+ facts?: InstanceCollectionFailureFacts,
147
+ ) {
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;
166
+ }
167
+ }
168
+
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;
182
+ }
183
+
184
+ interface CollectionResidency {
71
185
  readonly frameNumber: number;
72
186
  readonly residentGeneration: number | undefined;
73
187
  readonly lane: InstanceSubmissionLane;
74
- readonly uploadRanges: readonly InstanceUploadRange[];
188
+ readonly uploadRanges: readonly InstanceDirtyRange[];
75
189
  readonly uploadedBytes: number;
76
190
  readonly requestedBytes: number;
77
191
  readonly supportedBytes: number | undefined;
@@ -79,7 +193,73 @@ export interface InstanceResidency {
79
193
  readonly error: InstanceCollectionInspection['error'];
80
194
  }
81
195
 
82
- function appendRange(ranges: InstanceUploadRange[], start: number, end: number): void {
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 {
83
263
  if (start >= end) return;
84
264
  // Updates are allowed to arrive in any order. Insert at the first range
85
265
  // whose end reaches the new interval, then consume every range that starts
@@ -101,112 +281,312 @@ function appendRange(ranges: InstanceUploadRange[], start: number, end: number):
101
281
  ranges.splice(index, 0, { start, end });
102
282
  }
103
283
 
104
- interface CollectionRecord extends InstanceCollectionInfo {
105
- readonly world: World;
106
- readonly entity: number;
107
- readonly transforms: Float32Array;
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
+ );
108
298
  }
109
299
 
110
- /** Rebuildable per-renderer projection. World remains the authoring authority. */
111
- export class InstanceProjectionStore {
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 {
112
309
  private nextId = 1;
113
- private identities = new WeakMap<World, Map<number, InstanceCollectionId>>();
310
+ private epochValue = 0;
311
+ private disposed = false;
114
312
  private readonly records = new Map<InstanceCollectionId, CollectionRecord>();
313
+ private readonly residency = new Map<InstanceCollectionId, CollectionResidency>();
115
314
 
116
- project(world: World, entity: number, transforms: ArrayLike<number>): InstanceCollectionSnapshot {
117
- let entities = this.identities.get(world);
118
- if (entities === undefined) {
119
- entities = new Map();
120
- this.identities.set(world, entities);
121
- }
122
- let collectionId = entities.get(entity);
123
- if (collectionId === undefined) {
124
- collectionId = this.nextId++ as InstanceCollectionId;
125
- entities.set(entity, collectionId);
126
- }
127
- const previous = this.records.get(collectionId);
128
- const unchanged =
129
- previous !== undefined &&
130
- previous.transforms.length === transforms.length &&
131
- previous.transforms.every((value, index) => Object.is(value, transforms[index]));
132
- const record: CollectionRecord = unchanged
133
- ? previous
134
- : {
135
- collectionId,
136
- world,
137
- entity,
138
- transforms: new Float32Array(transforms),
139
- count: transforms.length / MATRIX_STRIDE,
140
- revision: (previous?.revision ?? 0) + 1,
141
- };
142
- this.records.set(collectionId, record);
143
- // Every consumer gets a complete snapshot. Reading never acknowledges an
144
- // upload; each GPU resident records its own successfully uploaded revision.
145
- return { ...this.info(record), transforms: record.transforms };
315
+ get epoch(): number {
316
+ return this.epochValue;
146
317
  }
147
318
 
148
- retain(ids: ReadonlySet<InstanceCollectionId>): void {
149
- for (const [id, record] of this.records) {
150
- if (ids.has(id)) continue;
151
- this.identities.get(record.world)?.delete(record.entity);
152
- this.records.delete(id);
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
+ );
153
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),
336
+ 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,
342
+ };
343
+ this.records.set(id, record);
344
+ this.epochValue += 1;
345
+ return ok(this.info(record));
154
346
  }
155
347
 
156
- /** Release one producer-owned collection when its render identity is removed. */
157
- release(world: World, entity: number): void {
158
- const entities = this.identities.get(world);
159
- const collectionId = entities?.get(entity);
160
- if (collectionId === undefined) return;
161
- entities?.delete(entity);
162
- this.records.delete(collectionId);
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));
163
365
  }
164
366
 
165
- dispose(): void {
166
- this.records.clear();
167
- this.identities = new WeakMap();
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 = [];
403
+ }
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
+ }
410
+
411
+ inspect(id: InstanceCollectionId): InstanceCollectionResult<InstanceCollectionInfo> {
412
+ const record = this.live('inspect', id);
413
+ return record.ok ? ok(this.info(record.value)) : record;
168
414
  }
169
415
 
170
416
  /**
171
417
  * Return detached residency facts for every live collection.
172
418
  *
173
- * @internal Joins CPU projection identity with the active device residency;
419
+ * @internal Record-stage evidence is reported through the two methods below;
174
420
  * callers only receive immutable PODs and never GPU handles.
175
421
  */
176
- _inspections(
177
- residency: ReadonlyMap<InstanceCollectionId, InstanceResidency> | undefined,
178
- frameNumber: number,
179
- ): readonly InstanceCollectionInspection[] {
422
+ _inspections(): readonly InstanceCollectionInspection[] {
180
423
  return Object.freeze(
181
- [...this.records.values()].map((record) =>
182
- this.projectInspection(record, residency?.get(record.collectionId), frameNumber),
183
- ),
424
+ [...this.records.values()].map((record) => this.projectInspection(record)),
184
425
  );
185
426
  }
186
427
 
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 {
440
+ if (!this.records.has(input.collectionId)) return;
441
+ 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 }));
455
+ this.residency.set(input.collectionId, {
456
+ frameNumber: input.frameNumber,
457
+ residentGeneration: input.residentGeneration,
458
+ lane: input.lane,
459
+ uploadRanges,
460
+ uploadedBytes: sameFrame ? previous.uploadedBytes + input.uploadedBytes : input.uploadedBytes,
461
+ requestedBytes: input.requestedBytes,
462
+ supportedBytes: input.supportedBytes,
463
+ backend: input.backend,
464
+ error: undefined,
465
+ });
466
+ }
467
+
468
+ /** @internal Renderer record owner reports a typed admission failure. */
469
+ _reportFailure(input: {
470
+ readonly collectionId: InstanceCollectionId;
471
+ readonly code: InstanceCollectionFailureCode;
472
+ readonly expected: string;
473
+ readonly hint: string;
474
+ readonly facts: InstanceCollectionFailureFacts;
475
+ }): void {
476
+ if (!this.records.has(input.collectionId)) return;
477
+ this.residency.set(input.collectionId, {
478
+ frameNumber: -1,
479
+ residentGeneration: undefined,
480
+ lane: 'unavailable',
481
+ uploadRanges: [],
482
+ uploadedBytes: 0,
483
+ requestedBytes: input.facts.requestedBytes,
484
+ supportedBytes: input.facts.supportedBytes,
485
+ backend: input.facts.backend,
486
+ error: {
487
+ code: input.code,
488
+ expected: input.expected,
489
+ hint: input.hint,
490
+ detail: { ...input.facts },
491
+ },
492
+ });
493
+ }
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 = {
506
+ ...this.info(value),
507
+ transforms: new Float32Array(value.transforms),
508
+ dirtyRanges: value.dirtyRanges.map((range) => ({ ...range })),
509
+ };
510
+ // Keep the current ranges stable for repeated reads by entities sharing
511
+ // this collection. The next authoring mutation starts a fresh interval
512
+ // set once this revision has been observed.
513
+ return ok(result);
514
+ }
515
+
516
+ release(id: InstanceCollectionId): InstanceCollectionResult<void> {
517
+ const record = this.records.get(id);
518
+ if (record === undefined) return err(missing('release', id));
519
+ if (record.released) {
520
+ return err(
521
+ new InstanceCollectionError(
522
+ 'instance-collection-released',
523
+ `instance collection ${Number(id)} has not already been released`,
524
+ 'do not reuse a released collection id; create a new collection',
525
+ {
526
+ operation: 'release',
527
+ expected: 'a live instance collection id',
528
+ actual: Number(id),
529
+ collectionId: id,
530
+ },
531
+ ),
532
+ );
533
+ }
534
+ record.released = true;
535
+ this.records.delete(id);
536
+ this.residency.delete(id);
537
+ this.epochValue += 1;
538
+ return ok(undefined);
539
+ }
540
+
541
+ /** Drop all canonical matrices during Renderer disposal. */
542
+ dispose(): void {
543
+ if (this.disposed) return;
544
+ this.disposed = true;
545
+ for (const record of this.records.values()) record.released = true;
546
+ this.records.clear();
547
+ this.residency.clear();
548
+ this.epochValue += 1;
549
+ }
550
+
551
+ private live(
552
+ operation: InstanceCollectionInvalidDetail['operation'],
553
+ id: InstanceCollectionId,
554
+ ): InstanceCollectionResult<CollectionRecord> {
555
+ if (!Number.isInteger(id) || id <= 0) {
556
+ return err(invalid(operation, 'collectionId is a positive integer', id, id));
557
+ }
558
+ if (this.disposed) {
559
+ return err(
560
+ new InstanceCollectionError(
561
+ 'instance-collection-released',
562
+ 'the Renderer-owned instance collection store is live',
563
+ 'create a new Renderer before using instance collections',
564
+ { operation, expected: 'a live collection store', actual: 'disposed', collectionId: id },
565
+ ),
566
+ );
567
+ }
568
+ const record = this.records.get(id);
569
+ return record === undefined ? err(missing(operation, id)) : ok(record);
570
+ }
571
+
187
572
  private info(record: CollectionRecord): InstanceCollectionInfo {
188
573
  return Object.freeze({
189
- collectionId: record.collectionId,
574
+ collectionId: record.id,
190
575
  count: record.count,
576
+ capacity: record.capacity,
191
577
  revision: record.revision,
192
578
  });
193
579
  }
194
580
 
195
- private projectInspection(
196
- record: CollectionRecord,
197
- residency: InstanceResidency | undefined,
198
- frameNumber: number,
199
- ): InstanceCollectionInspection {
581
+ private projectInspection(record: CollectionRecord): InstanceCollectionInspection {
582
+ const residency = this.residency.get(record.id);
200
583
  return Object.freeze({
201
584
  ...this.info(record),
202
585
  residentGeneration: residency?.residentGeneration,
203
586
  lane: residency?.lane ?? 'unresident',
204
- uploadRanges: Object.freeze(
205
- residency?.frameNumber === frameNumber
206
- ? residency.uploadRanges.map((range) => ({ ...range }))
207
- : [],
208
- ),
209
- uploadedBytes: residency?.frameNumber === frameNumber ? residency.uploadedBytes : 0,
587
+ dirtyRanges: Object.freeze(record.dirtyRanges.map((range) => ({ ...range }))),
588
+ uploadRanges: Object.freeze(residency?.uploadRanges.map((range) => ({ ...range })) ?? []),
589
+ uploadedBytes: residency?.uploadedBytes ?? 0,
210
590
  requestedBytes: residency?.requestedBytes ?? record.count * MATRIX_STRIDE * 4,
211
591
  supportedBytes: residency?.supportedBytes,
212
592
  backend: residency?.backend ?? 'unknown',
@@ -215,74 +595,3 @@ export class InstanceProjectionStore {
215
595
  });
216
596
  }
217
597
  }
218
-
219
- /** @internal Renderer record owner reports the accepted collection lane. */
220
- export function recordInstanceResidency(
221
- residency: Map<InstanceCollectionId, InstanceResidency>,
222
- input: {
223
- readonly collectionId: InstanceCollectionId;
224
- readonly frameNumber: number;
225
- readonly residentGeneration: number;
226
- readonly lane: Exclude<InstanceSubmissionLane, 'unresident' | 'unavailable'>;
227
- readonly uploadRanges: readonly InstanceUploadRange[];
228
- readonly uploadedBytes: number;
229
- readonly requestedBytes: number;
230
- readonly supportedBytes: number | undefined;
231
- readonly backend: InstanceBackendKind;
232
- },
233
- ): void {
234
- const previous = residency.get(input.collectionId);
235
- const sameFrame =
236
- previous !== undefined &&
237
- previous.frameNumber === input.frameNumber &&
238
- previous.error === undefined;
239
- const uploadRanges = sameFrame
240
- ? [...previous.uploadRanges].reduce(
241
- (ranges, range) => {
242
- appendRange(ranges, range.start, range.end);
243
- return ranges;
244
- },
245
- input.uploadRanges.map((range) => ({ ...range })),
246
- )
247
- : input.uploadRanges.map((range) => ({ ...range }));
248
- residency.set(input.collectionId, {
249
- frameNumber: input.frameNumber,
250
- residentGeneration: input.residentGeneration,
251
- lane: input.lane,
252
- uploadRanges,
253
- uploadedBytes: sameFrame ? previous.uploadedBytes + input.uploadedBytes : input.uploadedBytes,
254
- requestedBytes: input.requestedBytes,
255
- supportedBytes: input.supportedBytes,
256
- backend: input.backend,
257
- error: undefined,
258
- });
259
- }
260
-
261
- /** @internal Renderer record owner reports a typed admission failure. */
262
- export function recordInstanceFailure(
263
- residency: Map<InstanceCollectionId, InstanceResidency>,
264
- input: {
265
- readonly collectionId: InstanceCollectionId;
266
- readonly code: InstanceCollectionFailureCode;
267
- readonly expected: string;
268
- readonly hint: string;
269
- readonly facts: InstanceCollectionFailureFacts;
270
- },
271
- ): void {
272
- residency.set(input.collectionId, {
273
- frameNumber: -1,
274
- residentGeneration: undefined,
275
- lane: 'unavailable',
276
- uploadRanges: [],
277
- uploadedBytes: 0,
278
- requestedBytes: input.facts.requestedBytes,
279
- supportedBytes: input.facts.supportedBytes,
280
- backend: input.facts.backend,
281
- error: {
282
- code: input.code,
283
- expected: input.expected,
284
- hint: input.hint,
285
- detail: { ...input.facts },
286
- },
287
- });
288
- }