@forgeax/engine-render 0.1.33 → 0.1.35

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 +1062 -127
  2. package/dist/assembly/backend-contract.d.ts +2 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  5. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  6. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  7. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  8. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  9. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  10. package/dist/assembly/device-feature-admission.d.ts +2 -2
  11. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  12. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  15. package/dist/assembly/factory.d.ts +1 -1
  16. package/dist/assembly/factory.d.ts.map +1 -1
  17. package/dist/assembly/host-contract.d.ts +6 -5
  18. package/dist/assembly/host-contract.d.ts.map +1 -1
  19. package/dist/assembly/material/assembly.d.ts.map +1 -1
  20. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  21. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  22. package/dist/assembly/material-shader-policy.d.ts +16 -2
  23. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  24. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  26. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  27. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  28. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  29. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  30. package/dist/assembly/render-target-host.d.ts +5 -0
  31. package/dist/assembly/render-target-host.d.ts.map +1 -1
  32. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  33. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  34. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  35. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  36. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  37. package/dist/assembly/renderer-inspection.d.ts +11 -0
  38. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  41. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  42. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +1 -1
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  46. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  47. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  48. package/dist/assembly/webgpu-renderer.d.ts +2 -1
  49. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  50. package/dist/authoring.mjs +2 -4
  51. package/dist/authoring.mjs.map +1 -1
  52. package/dist/barrel-distortion.d.ts +47 -0
  53. package/dist/barrel-distortion.d.ts.map +1 -0
  54. package/dist/chunk-3XUBWRY2.mjs +1842 -0
  55. package/dist/chunk-3XUBWRY2.mjs.map +1 -0
  56. package/dist/{chunk-OO3DRYK7.mjs → chunk-G6HDNGY7.mjs} +2400 -1767
  57. package/dist/chunk-G6HDNGY7.mjs.map +1 -0
  58. package/dist/{chunk-ZDQWGQW7.mjs → chunk-LM5IE7GF.mjs} +4 -4
  59. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
  60. package/dist/{chunk-VOZWDM3L.mjs → chunk-LNIUIKQ7.mjs} +1514 -498
  61. package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
  62. package/dist/chunk-MXTWKZO4.mjs +3268 -0
  63. package/dist/chunk-MXTWKZO4.mjs.map +1 -0
  64. package/dist/chunk-MZ4C7EHF.mjs +6942 -0
  65. package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
  66. package/dist/chunk-RIPAEGI6.mjs +48 -0
  67. package/dist/chunk-RIPAEGI6.mjs.map +1 -0
  68. package/dist/{chunk-LEAXOMYJ.mjs → chunk-SGPUJW3F.mjs} +117 -5
  69. package/dist/chunk-SGPUJW3F.mjs.map +1 -0
  70. package/dist/{chunk-PA5DRJNI.mjs → chunk-X2KA6WHM.mjs} +29 -4
  71. package/dist/chunk-X2KA6WHM.mjs.map +1 -0
  72. package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
  73. package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
  74. package/dist/cloud/density.d.ts +55 -0
  75. package/dist/cloud/density.d.ts.map +1 -0
  76. package/dist/cloud/extract.d.ts +25 -0
  77. package/dist/cloud/extract.d.ts.map +1 -0
  78. package/dist/cloud/feature.d.ts +57 -0
  79. package/dist/cloud/feature.d.ts.map +1 -0
  80. package/dist/cloud/frame-context.d.ts +8 -0
  81. package/dist/cloud/frame-context.d.ts.map +1 -0
  82. package/dist/cloud/inspection.d.ts +59 -0
  83. package/dist/cloud/inspection.d.ts.map +1 -0
  84. package/dist/cloud/optics.d.ts +56 -0
  85. package/dist/cloud/optics.d.ts.map +1 -0
  86. package/dist/cloud/parameters.d.ts +73 -0
  87. package/dist/cloud/parameters.d.ts.map +1 -0
  88. package/dist/cloud/resources.d.ts +60 -0
  89. package/dist/cloud/resources.d.ts.map +1 -0
  90. package/dist/cloud/shadow.d.ts +42 -0
  91. package/dist/cloud/shadow.d.ts.map +1 -0
  92. package/dist/cloud/temporal.d.ts +74 -0
  93. package/dist/cloud/temporal.d.ts.map +1 -0
  94. package/dist/components/barrel-distortion.d.ts +13 -0
  95. package/dist/components/barrel-distortion.d.ts.map +1 -0
  96. package/dist/components/cloud-layer.d.ts +29 -0
  97. package/dist/components/cloud-layer.d.ts.map +1 -0
  98. package/dist/components/index.d.ts +2 -0
  99. package/dist/components/index.d.ts.map +1 -1
  100. package/dist/components/instances.d.ts +20 -6
  101. package/dist/components/instances.d.ts.map +1 -1
  102. package/dist/construct-renderer.d.ts +1 -1
  103. package/dist/construct-renderer.d.ts.map +1 -1
  104. package/dist/construct-renderer.mjs +8406 -5785
  105. package/dist/construct-renderer.mjs.map +1 -1
  106. package/dist/device/gpu-residency.d.ts +19 -19
  107. package/dist/device/gpu-residency.d.ts.map +1 -1
  108. package/dist/dynamic-geometry.d.ts +5 -1
  109. package/dist/dynamic-geometry.d.ts.map +1 -1
  110. package/dist/errors/cloud.d.ts +59 -0
  111. package/dist/errors/cloud.d.ts.map +1 -0
  112. package/dist/errors/render.d.ts +20 -5
  113. package/dist/errors/render.d.ts.map +1 -1
  114. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  115. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  116. package/dist/extract/camera.d.ts.map +1 -1
  117. package/dist/extract/contracts.d.ts +5 -1
  118. package/dist/extract/contracts.d.ts.map +1 -1
  119. package/dist/extract/material-context.d.ts +7 -0
  120. package/dist/extract/material-context.d.ts.map +1 -0
  121. package/dist/features/barrel-distortion.d.ts +29 -0
  122. package/dist/features/barrel-distortion.d.ts.map +1 -0
  123. package/dist/features/error-reporting.d.ts +6 -2
  124. package/dist/features/error-reporting.d.ts.map +1 -1
  125. package/dist/features/host.d.ts +15 -0
  126. package/dist/features/host.d.ts.map +1 -1
  127. package/dist/features/plan.d.ts +10 -0
  128. package/dist/features/plan.d.ts.map +1 -1
  129. package/dist/features/render-graph-contribution.d.ts +5 -0
  130. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  131. package/dist/features/render-graph-raster.d.ts +1 -0
  132. package/dist/features/render-graph-raster.d.ts.map +1 -1
  133. package/dist/features/targets.d.ts +2 -0
  134. package/dist/features/targets.d.ts.map +1 -1
  135. package/dist/features/types.d.ts +48 -0
  136. package/dist/features/types.d.ts.map +1 -1
  137. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  138. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  139. package/dist/glyph-text-layout-system.d.ts +1 -1
  140. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  141. package/dist/gpu-dirty-ranges.d.ts +11 -0
  142. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  143. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  144. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  145. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  146. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  147. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  148. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  149. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  150. package/dist/gpu-driven/production-raster.d.ts +47 -3
  151. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  152. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  153. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  154. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  155. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  156. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  157. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  158. package/dist/gpu-scene.d.ts +5 -0
  159. package/dist/gpu-scene.d.ts.map +1 -1
  160. package/dist/hdrp-buffers.d.ts +2 -2
  161. package/dist/hdrp-buffers.d.ts.map +1 -1
  162. package/dist/ibl/frame-resources.d.ts.map +1 -1
  163. package/dist/ibl/skylight-bind-group.d.ts +14 -5
  164. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  165. package/dist/index.d.ts +30 -7
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.mjs +780 -9
  168. package/dist/index.mjs.map +1 -1
  169. package/dist/inspection-types.d.ts +135 -1
  170. package/dist/inspection-types.d.ts.map +1 -1
  171. package/dist/instance-buffer-cache.d.ts +4 -4
  172. package/dist/instance-buffer-cache.d.ts.map +1 -1
  173. package/dist/instances.d.ts +47 -100
  174. package/dist/instances.d.ts.map +1 -1
  175. package/dist/internal.mjs +7 -8
  176. package/dist/internal.mjs.map +1 -1
  177. package/dist/pbr-pipeline.d.ts +22 -4
  178. package/dist/pbr-pipeline.d.ts.map +1 -1
  179. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  180. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  181. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  182. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  183. package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
  184. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
  185. package/dist/pipeline/standard-output/resources.d.ts +2 -2
  186. package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
  187. package/dist/pipeline/standard-output/types.d.ts +4 -2
  188. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  189. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  190. package/dist/pipeline/standard-post.d.ts.map +1 -1
  191. package/dist/pipeline-builder.d.ts +1 -1
  192. package/dist/pipeline-builder.d.ts.map +1 -1
  193. package/dist/plugin.d.ts.map +1 -1
  194. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  195. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  196. package/dist/publication/contract.d.ts +77 -0
  197. package/dist/publication/contract.d.ts.map +1 -0
  198. package/dist/publication/dependencies.d.ts +7 -0
  199. package/dist/publication/dependencies.d.ts.map +1 -0
  200. package/dist/publication/prepare-geometry.d.ts +9 -0
  201. package/dist/publication/prepare-geometry.d.ts.map +1 -0
  202. package/dist/publication/programs.d.ts +5 -0
  203. package/dist/publication/programs.d.ts.map +1 -0
  204. package/dist/publication/publisher.d.ts +33 -0
  205. package/dist/publication/publisher.d.ts.map +1 -0
  206. package/dist/publication/receiver.d.ts +29 -0
  207. package/dist/publication/receiver.d.ts.map +1 -0
  208. package/dist/publication/resource-scope.d.ts +18 -0
  209. package/dist/publication/resource-scope.d.ts.map +1 -0
  210. package/dist/publication/targets.d.ts +33 -0
  211. package/dist/publication/targets.d.ts.map +1 -0
  212. package/dist/publication/video.d.ts +5 -0
  213. package/dist/publication/video.d.ts.map +1 -0
  214. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  215. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  216. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  218. package/dist/record/fold-buckets.d.ts +95 -0
  219. package/dist/record/fold-buckets.d.ts.map +1 -0
  220. package/dist/record/fold-instance-buffer.d.ts +6 -0
  221. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  222. package/dist/record/frame-lighting.d.ts +1 -0
  223. package/dist/record/frame-lighting.d.ts.map +1 -1
  224. package/dist/record/frame-snapshot.d.ts +43 -9
  225. package/dist/record/frame-snapshot.d.ts.map +1 -1
  226. package/dist/record/frame.d.ts +15 -65
  227. package/dist/record/frame.d.ts.map +1 -1
  228. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  229. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  230. package/dist/record/gpu-timing.d.ts +8 -0
  231. package/dist/record/gpu-timing.d.ts.map +1 -1
  232. package/dist/record/helpers.d.ts +2 -2
  233. package/dist/record/helpers.d.ts.map +1 -1
  234. package/dist/record/main-pass-geometry.d.ts +22 -6
  235. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  236. package/dist/record/main-pass-material.d.ts +14 -10
  237. package/dist/record/main-pass-material.d.ts.map +1 -1
  238. package/dist/record/main-pass-sprite-draws.d.ts +3 -16
  239. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  240. package/dist/record/main-pass.d.ts +13 -2
  241. package/dist/record/main-pass.d.ts.map +1 -1
  242. package/dist/record/motion-blur-receipt.d.ts +11 -0
  243. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  244. package/dist/record/prepared-material-bindings.d.ts +3 -3
  245. package/dist/record/prepared-material-bindings.d.ts.map +1 -1
  246. package/dist/record/probe-blend-buffer.d.ts +16 -0
  247. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  248. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  249. package/dist/record/render-context.d.ts +24 -5
  250. package/dist/record/render-context.d.ts.map +1 -1
  251. package/dist/record/shadow-pass.d.ts +2 -0
  252. package/dist/record/shadow-pass.d.ts.map +1 -1
  253. package/dist/record/skybox-post-pass.d.ts +1 -1
  254. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  255. package/dist/record/sprite-instance-buffer.d.ts +31 -0
  256. package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
  257. package/dist/record/target-capture-graph.d.ts +19 -0
  258. package/dist/record/target-capture-graph.d.ts.map +1 -0
  259. package/dist/record/typed-frame-graph.d.ts +24 -15
  260. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  261. package/dist/record/view-ubo.d.ts +11 -3
  262. package/dist/record/view-ubo.d.ts.map +1 -1
  263. package/dist/record/volume-params.d.ts +9 -0
  264. package/dist/record/volume-params.d.ts.map +1 -0
  265. package/dist/recovery/render-system-candidate.d.ts +14 -4
  266. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  267. package/dist/reflection/record-owner.d.ts.map +1 -1
  268. package/dist/render-contract.d.ts +46 -5
  269. package/dist/render-contract.d.ts.map +1 -1
  270. package/dist/render-graph-primitives.d.ts.map +1 -1
  271. package/dist/render-pipeline.d.ts +103 -2
  272. package/dist/render-pipeline.d.ts.map +1 -1
  273. package/dist/render-system-extract-tail.d.ts +3 -2
  274. package/dist/render-system-extract-tail.d.ts.map +1 -1
  275. package/dist/render-system-extract.d.ts +18 -9
  276. package/dist/render-system-extract.d.ts.map +1 -1
  277. package/dist/render-system-presentation.d.ts +23 -0
  278. package/dist/render-system-presentation.d.ts.map +1 -0
  279. package/dist/render-system-producer-roots.d.ts +10 -0
  280. package/dist/render-system-producer-roots.d.ts.map +1 -0
  281. package/dist/render-system-projections.d.ts +3 -2
  282. package/dist/render-system-projections.d.ts.map +1 -1
  283. package/dist/render-system-residency.d.ts +12 -0
  284. package/dist/render-system-residency.d.ts.map +1 -0
  285. package/dist/render-system.d.ts +22 -21
  286. package/dist/render-system.d.ts.map +1 -1
  287. package/dist/scene/probe-blend.d.ts +27 -0
  288. package/dist/scene/probe-blend.d.ts.map +1 -1
  289. package/dist/scene/render-scene.d.ts +18 -7
  290. package/dist/scene/render-scene.d.ts.map +1 -1
  291. package/dist/scene/render-source.d.ts +42 -0
  292. package/dist/scene/render-source.d.ts.map +1 -0
  293. package/dist/scene/source-systems.d.ts +6 -0
  294. package/dist/scene/source-systems.d.ts.map +1 -0
  295. package/dist/ssao-buffers.d.ts +9 -0
  296. package/dist/ssao-buffers.d.ts.map +1 -1
  297. package/dist/surface/dynamic-input.d.ts +133 -0
  298. package/dist/surface/dynamic-input.d.ts.map +1 -0
  299. package/dist/surface/gpu-driven.d.ts +41 -0
  300. package/dist/surface/gpu-driven.d.ts.map +1 -0
  301. package/dist/surface/submission-observation.d.ts +136 -0
  302. package/dist/surface/submission-observation.d.ts.map +1 -0
  303. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  304. package/dist/systems/skin-palette-types.d.ts +10 -0
  305. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  306. package/dist/systems/transparent-dispatch.d.ts +2 -2
  307. package/dist/systems/transparent-dispatch.d.ts.map +1 -1
  308. package/dist/systems/transparent-sort-config.d.ts +2 -1
  309. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  310. package/dist/temporal/gpu.d.ts +13 -1
  311. package/dist/temporal/gpu.d.ts.map +1 -1
  312. package/dist/temporal/index.mjs +6 -7
  313. package/dist/temporal/inspection.d.ts.map +1 -1
  314. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  315. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  316. package/dist/transmission/single-layer-medium.d.ts +89 -0
  317. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  318. package/dist/typed-render-graph-primitives.d.ts +14 -2
  319. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  320. package/dist/volume/component.d.ts +9 -4
  321. package/dist/volume/component.d.ts.map +1 -1
  322. package/dist/volume/extract.d.ts +1 -1
  323. package/dist/volume/extract.d.ts.map +1 -1
  324. package/dist/volume/inspection.d.ts +2 -0
  325. package/dist/volume/inspection.d.ts.map +1 -1
  326. package/dist/volume/passes.d.ts +4 -1
  327. package/dist/volume/passes.d.ts.map +1 -1
  328. package/dist/volume/resources.d.ts.map +1 -1
  329. package/package.json +22 -21
  330. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  331. package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
  332. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  333. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  334. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  335. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  336. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  337. package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
  338. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  339. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  340. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  341. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  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-material-artifacts.unit.test.ts +143 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +5 -6
  348. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  349. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  350. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  351. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  352. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  353. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  354. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  355. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  356. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  357. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  358. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  359. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  360. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  361. package/src/__tests__/instances-store.unit.test.ts +97 -305
  362. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  363. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
  364. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +145 -0
  365. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  366. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  367. package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
  368. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  369. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  370. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  371. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  372. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  373. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  374. package/src/__tests__/physical-clearcoat.integration.test.ts +66 -8
  375. package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
  376. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  377. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  378. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  379. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  380. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  381. package/src/__tests__/render-error-code-owner.test-d.ts +8 -0
  382. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  383. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  384. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  385. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  386. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  387. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  388. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  389. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  390. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  391. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  392. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -8
  393. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  394. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  395. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  396. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  397. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  398. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  399. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  400. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  401. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  402. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  403. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  404. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  405. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  406. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  407. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  408. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  409. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  410. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  411. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  412. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  413. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  414. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  415. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  416. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  417. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  418. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  419. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  420. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  421. package/src/assembly/backend-contract.ts +30 -0
  422. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  423. package/src/assembly/canvas-draw-guard.ts +11 -0
  424. package/src/assembly/cloud-shadow-entry.ts +22 -0
  425. package/src/assembly/device-feature-admission.ts +2 -2
  426. package/src/assembly/dynamic-geometry-host.ts +65 -37
  427. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  428. package/src/assembly/factory.ts +2 -30
  429. package/src/assembly/host-contract.ts +8 -5
  430. package/src/assembly/material/assembly.ts +25 -13
  431. package/src/assembly/material/pipeline-helpers.ts +53 -12
  432. package/src/assembly/material-shader-policy.ts +55 -0
  433. package/src/assembly/material-shader-prewarm.ts +21 -10
  434. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  435. package/src/assembly/recovery/renderer-recover.ts +50 -18
  436. package/src/assembly/render-feature-post-processes.ts +54 -0
  437. package/src/assembly/render-target-host.ts +57 -47
  438. package/src/assembly/renderer-facade.ts +7 -2
  439. package/src/assembly/renderer-feature-inspection.ts +8 -2
  440. package/src/assembly/renderer-frame-transaction.ts +23 -0
  441. package/src/assembly/renderer-inspection.ts +28 -0
  442. package/src/assembly/skin-palette-owner.ts +1 -1
  443. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  444. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  445. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  446. package/src/assembly/webgpu-ready.ts +116 -62
  447. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  448. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  449. package/src/assembly/webgpu-renderer.ts +303 -313
  450. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  451. package/src/barrel-distortion.ts +247 -0
  452. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  453. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  454. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  455. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  456. package/src/cloud/density.ts +600 -0
  457. package/src/cloud/extract.ts +110 -0
  458. package/src/cloud/feature.ts +1810 -0
  459. package/src/cloud/frame-context.ts +42 -0
  460. package/src/cloud/inspection.ts +130 -0
  461. package/src/cloud/optics.ts +285 -0
  462. package/src/cloud/parameters.ts +255 -0
  463. package/src/cloud/resources.ts +122 -0
  464. package/src/cloud/shadow.ts +167 -0
  465. package/src/cloud/temporal.ts +226 -0
  466. package/src/components/barrel-distortion.ts +46 -0
  467. package/src/components/cloud-layer.ts +47 -0
  468. package/src/components/index.ts +2 -0
  469. package/src/components/instances.ts +18 -45
  470. package/src/components/sprite-instances.ts +1 -1
  471. package/src/construct-renderer.ts +1 -1
  472. package/src/device/gpu-residency.ts +26 -25
  473. package/src/dynamic-geometry.ts +12 -1
  474. package/src/errors/cloud.ts +103 -0
  475. package/src/errors/render.ts +47 -8
  476. package/src/examples/single-layer-medium-surface.ts +59 -0
  477. package/src/extract/camera.ts +15 -1
  478. package/src/extract/contracts.ts +5 -0
  479. package/src/extract/material-context.ts +21 -0
  480. package/src/features/barrel-distortion.ts +172 -0
  481. package/src/features/error-reporting.ts +26 -6
  482. package/src/features/host.ts +128 -19
  483. package/src/features/plan.ts +10 -0
  484. package/src/features/render-graph-contribution.ts +9 -0
  485. package/src/features/render-graph-raster.ts +45 -3
  486. package/src/features/targets.ts +66 -0
  487. package/src/features/types.ts +51 -0
  488. package/src/fullscreen-post-process-pass.ts +41 -9
  489. package/src/glyph-text-layout-system.ts +2 -2
  490. package/src/gpu-dirty-ranges.ts +48 -0
  491. package/src/gpu-driven/batch-topology.ts +53 -0
  492. package/src/gpu-driven/material-artifacts.ts +33 -25
  493. package/src/gpu-driven/prepared-draw.ts +12 -4
  494. package/src/gpu-driven/production-raster-material.ts +1894 -0
  495. package/src/gpu-driven/production-raster.ts +825 -784
  496. package/src/gpu-driven/resource-allocation.ts +142 -0
  497. package/src/gpu-driven/shadow-ownership.ts +71 -0
  498. package/src/gpu-driven/view-gpu.ts +164 -10
  499. package/src/gpu-scene.ts +75 -84
  500. package/src/hdrp-buffers.ts +4 -3
  501. package/src/ibl/frame-resources.ts +0 -1
  502. package/src/ibl/skylight-bind-group.ts +62 -32
  503. package/src/index.ts +205 -9
  504. package/src/inspection-types.ts +162 -0
  505. package/src/instance-buffer-cache.ts +4 -4
  506. package/src/instances.ts +152 -569
  507. package/src/pbr-pipeline.ts +230 -30
  508. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  509. package/src/pipeline/standard-forward-lane.ts +313 -57
  510. package/src/pipeline/standard-output/graph.ts +8 -2
  511. package/src/pipeline/standard-output/lut-gpu.ts +3 -3
  512. package/src/pipeline/standard-output/resources.ts +2 -2
  513. package/src/pipeline/standard-output/types.ts +12 -1
  514. package/src/pipeline/standard-pipeline.ts +291 -18
  515. package/src/pipeline/standard-post.ts +90 -24
  516. package/src/pipeline-builder.ts +1 -1
  517. package/src/plugin.ts +4 -0
  518. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  519. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  520. package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
  521. package/src/publication/__tests__/features.integration.test.ts +122 -0
  522. package/src/publication/__tests__/programs.unit.test.ts +25 -0
  523. package/src/publication/__tests__/publication.integration.test.ts +370 -0
  524. package/src/publication/__tests__/targets.integration.test.ts +120 -0
  525. package/src/publication/__tests__/video.browser.test.ts +50 -0
  526. package/src/publication/contract.ts +104 -0
  527. package/src/publication/dependencies.ts +54 -0
  528. package/src/publication/prepare-geometry.ts +94 -0
  529. package/src/publication/programs.ts +45 -0
  530. package/src/publication/publisher.ts +618 -0
  531. package/src/publication/receiver.ts +297 -0
  532. package/src/publication/resource-scope.ts +31 -0
  533. package/src/publication/targets.ts +182 -0
  534. package/src/publication/video.ts +33 -0
  535. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  536. package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
  537. package/src/record/__tests__/sprite-material-abi.unit.test.ts +9 -11
  538. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  539. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  540. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  541. package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
  542. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  543. package/src/record/barrel-distortion-frame.ts +110 -0
  544. package/src/record/dynamic-geometry-consumption.ts +39 -9
  545. package/src/record/fold-buckets.ts +855 -0
  546. package/src/record/fold-instance-buffer.ts +51 -0
  547. package/src/record/frame-lighting.ts +36 -2
  548. package/src/record/frame-snapshot.ts +45 -9
  549. package/src/record/frame.ts +258 -1105
  550. package/src/record/gpu-draw-receipts.ts +38 -0
  551. package/src/record/gpu-timing.ts +48 -5
  552. package/src/record/helpers.ts +2 -2
  553. package/src/record/main-pass-geometry.ts +272 -84
  554. package/src/record/main-pass-material.ts +102 -36
  555. package/src/record/main-pass-sprite-draws.ts +13 -217
  556. package/src/record/main-pass.ts +164 -27
  557. package/src/record/motion-blur-receipt.ts +91 -0
  558. package/src/record/prepared-material-bindings.ts +11 -6
  559. package/src/record/probe-blend-buffer.ts +180 -0
  560. package/src/record/recovery-pipeline.ts +35 -3
  561. package/src/record/render-context.ts +41 -5
  562. package/src/record/shadow-pass.ts +30 -4
  563. package/src/record/skybox-post-pass.ts +28 -4
  564. package/src/record/sprite-instance-buffer.ts +155 -0
  565. package/src/record/target-capture-graph.ts +258 -0
  566. package/src/record/typed-frame-graph.ts +776 -340
  567. package/src/record/view-ubo.ts +27 -4
  568. package/src/record/volume-params.ts +225 -0
  569. package/src/recovery/render-system-candidate.ts +243 -50
  570. package/src/reflection/record-owner.ts +7 -3
  571. package/src/render-contract.ts +54 -5
  572. package/src/render-graph-primitives.ts +7 -1
  573. package/src/render-pipeline.ts +130 -0
  574. package/src/render-system-extract-tail.ts +90 -78
  575. package/src/render-system-extract.ts +76 -76
  576. package/src/render-system-presentation.ts +56 -0
  577. package/src/render-system-producer-roots.ts +96 -0
  578. package/src/render-system-projections.ts +3 -2
  579. package/src/render-system-residency.ts +159 -0
  580. package/src/render-system.ts +421 -408
  581. package/src/scene/probe-blend.ts +96 -4
  582. package/src/scene/render-scene.ts +416 -337
  583. package/src/scene/render-source.ts +90 -0
  584. package/src/scene/source-systems.ts +33 -0
  585. package/src/ssao-buffers.ts +95 -2
  586. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  587. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  588. package/src/surface/dynamic-input.ts +658 -0
  589. package/src/surface/gpu-driven.ts +147 -0
  590. package/src/surface/submission-observation.ts +517 -0
  591. package/src/systems/skin-palette-allocator.ts +5 -1
  592. package/src/systems/skin-palette-types.ts +11 -0
  593. package/src/systems/transparent-dispatch.ts +2 -2
  594. package/src/systems/transparent-sort-config.ts +3 -1
  595. package/src/temporal/gpu.ts +101 -17
  596. package/src/temporal/inspection.ts +7 -1
  597. package/src/temporal/standard-scene-data.ts +5 -0
  598. package/src/temporal/target-coverage-attachment.ts +4 -0
  599. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  600. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  601. package/src/transmission/single-layer-medium.ts +322 -0
  602. package/src/typed-render-graph-primitives.ts +70 -2
  603. package/src/volume/component.ts +10 -9
  604. package/src/volume/extract.ts +11 -5
  605. package/src/volume/inspection.ts +3 -0
  606. package/src/volume/passes.ts +87 -4
  607. package/src/volume/resources.ts +2 -1
  608. package/dist/chunk-3RTCJTH4.mjs +0 -1610
  609. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  610. package/dist/chunk-BLXGONR2.mjs.map +0 -1
  611. package/dist/chunk-ILQ5MEZF.mjs +0 -32
  612. package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
  613. package/dist/chunk-LEAXOMYJ.mjs.map +0 -1
  614. package/dist/chunk-NB2S7ZRX.mjs +0 -1783
  615. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  616. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  617. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  618. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  619. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  620. package/dist/chunk-PLAXOOX5.mjs +0 -1907
  621. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  622. package/dist/chunk-RXZ3RGOU.mjs +0 -53
  623. package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
  624. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -0,0 +1,226 @@
1
+ import type { CloudQuality } from '../components/cloud-layer';
2
+
3
+ export type CloudTemporalResetReason =
4
+ | 'authoring-generation'
5
+ | 'camera-cut'
6
+ | 'resize'
7
+ | 'recovery'
8
+ | 'time-discontinuity'
9
+ | 'cloud-shadow-revision'
10
+ | 'device-generation'
11
+ | 'history-missing'
12
+ | 'reprojection-outside'
13
+ | 'scene-depth-disocclusion';
14
+
15
+ export interface CloudTemporalSignature {
16
+ readonly sourceKey: string;
17
+ readonly viewId: string;
18
+ readonly authoringGeneration: number;
19
+ readonly cloudShadowRevision: number;
20
+ readonly cameraRevision: number;
21
+ readonly deviceGeneration: number;
22
+ readonly width: number;
23
+ readonly height: number;
24
+ readonly timeSeconds: number;
25
+ readonly quality: CloudQuality;
26
+ /** Scene-depth producer revision used to reject disoccluded history. */
27
+ readonly sceneDepthVersion?: number;
28
+ }
29
+
30
+ export interface CloudHistory {
31
+ readonly width: number;
32
+ readonly height: number;
33
+ readonly signature: string;
34
+ readonly temporal: CloudTemporalSignature;
35
+ readonly generation: number;
36
+ readonly valid: boolean;
37
+ }
38
+
39
+ export interface CloudTemporalDecision {
40
+ readonly reset: boolean;
41
+ readonly reasons: readonly CloudTemporalResetReason[];
42
+ readonly signature: string;
43
+ readonly history: CloudHistory | undefined;
44
+ }
45
+
46
+ export interface CloudTemporalFrame {
47
+ readonly signature: CloudTemporalSignature;
48
+ readonly history: CloudHistory | undefined;
49
+ readonly reset: boolean;
50
+ readonly reasons: readonly CloudTemporalResetReason[];
51
+ }
52
+
53
+ export interface CloudHistoryReprojectionInput {
54
+ readonly currentDepth: number;
55
+ readonly historyDepth: number;
56
+ readonly motion: readonly [number, number];
57
+ readonly currentPixel: readonly [number, number];
58
+ readonly historySize: readonly [number, number];
59
+ readonly depthTolerance?: number;
60
+ }
61
+
62
+ export interface CloudHistoryReprojection {
63
+ readonly accepted: boolean;
64
+ readonly historyUv: readonly [number, number];
65
+ readonly weight: number;
66
+ readonly reason: 'accepted' | 'outside' | 'depth-disocclusion';
67
+ }
68
+
69
+ export function cloudTemporalSignature(input: CloudTemporalSignature): string {
70
+ return [
71
+ 'cloud-temporal-v1',
72
+ input.viewId,
73
+ input.sourceKey,
74
+ input.authoringGeneration,
75
+ input.cloudShadowRevision,
76
+ input.cameraRevision,
77
+ input.deviceGeneration,
78
+ input.width,
79
+ input.height,
80
+ input.timeSeconds,
81
+ input.quality,
82
+ input.sceneDepthVersion ?? 0,
83
+ ].join(':');
84
+ }
85
+
86
+ function sameLayout(left: CloudTemporalSignature, right: CloudTemporalSignature): boolean {
87
+ return left.viewId === right.viewId && left.width === right.width && left.height === right.height;
88
+ }
89
+
90
+ /** Compare the facts that make a cloud history safe to reuse. */
91
+ export function cloudTemporalResetReasons(
92
+ previous: CloudTemporalSignature | undefined,
93
+ next: CloudTemporalSignature,
94
+ options: { readonly cameraCut?: boolean; readonly recovery?: boolean } = {},
95
+ ): readonly CloudTemporalResetReason[] {
96
+ if (previous === undefined) return ['history-missing'];
97
+ const reasons: CloudTemporalResetReason[] = [];
98
+ if (
99
+ previous.sourceKey !== next.sourceKey ||
100
+ previous.authoringGeneration !== next.authoringGeneration
101
+ ) {
102
+ reasons.push('authoring-generation');
103
+ }
104
+ if (previous.cloudShadowRevision !== next.cloudShadowRevision)
105
+ reasons.push('cloud-shadow-revision');
106
+ if (previous.deviceGeneration !== next.deviceGeneration) reasons.push('device-generation');
107
+ if (
108
+ previous.sceneDepthVersion !== undefined &&
109
+ next.sceneDepthVersion !== undefined &&
110
+ previous.sceneDepthVersion !== next.sceneDepthVersion
111
+ ) {
112
+ reasons.push('scene-depth-disocclusion');
113
+ }
114
+ if (!sameLayout(previous, next)) reasons.push('resize');
115
+ if (options.cameraCut === true || previous.cameraRevision !== next.cameraRevision)
116
+ reasons.push('camera-cut');
117
+ const dt = next.timeSeconds - previous.timeSeconds;
118
+ if (!Number.isFinite(dt) || dt < 0 || dt > 0.5) reasons.push('time-discontinuity');
119
+ if (options.recovery === true) reasons.push('recovery');
120
+ return Object.freeze(reasons);
121
+ }
122
+
123
+ export function createCloudHistory(
124
+ signature: CloudTemporalSignature,
125
+ generation: number,
126
+ valid = false,
127
+ ): CloudHistory {
128
+ return Object.freeze({
129
+ width: Math.max(1, Math.floor(signature.width)),
130
+ height: Math.max(1, Math.floor(signature.height)),
131
+ signature: cloudTemporalSignature(signature),
132
+ temporal: Object.freeze({ ...signature }),
133
+ generation,
134
+ valid,
135
+ });
136
+ }
137
+
138
+ /** Per-view histories are keyed by the renderer's view identity. */
139
+ export class CloudHistoryStore {
140
+ private readonly maxViews: number;
141
+ private readonly entries = new Map<
142
+ string,
143
+ { readonly history: CloudHistory; readonly signature: CloudTemporalSignature }
144
+ >();
145
+
146
+ constructor(maxViews = 4) {
147
+ this.maxViews = Math.max(1, Math.floor(maxViews));
148
+ }
149
+
150
+ begin(
151
+ signature: CloudTemporalSignature,
152
+ options: { readonly cameraCut?: boolean; readonly recovery?: boolean } = {},
153
+ ): CloudTemporalDecision {
154
+ const key = signature.viewId;
155
+ const previousEntry = this.entries.get(key);
156
+ const previous = previousEntry?.history;
157
+ const reasons = cloudTemporalResetReasons(previousEntry?.signature, signature, options);
158
+ const reset = reasons.length > 0;
159
+ return Object.freeze({
160
+ reset,
161
+ reasons,
162
+ signature: cloudTemporalSignature(signature),
163
+ history: reset ? undefined : previous,
164
+ });
165
+ }
166
+
167
+ commit(signature: CloudTemporalSignature, history: CloudHistory): void {
168
+ if (
169
+ history.width !== Math.max(1, Math.floor(signature.width)) ||
170
+ history.height !== Math.max(1, Math.floor(signature.height))
171
+ ) {
172
+ this.entries.delete(signature.viewId);
173
+ return;
174
+ }
175
+ this.entries.set(signature.viewId, { history, signature: Object.freeze({ ...signature }) });
176
+ while (this.entries.size > this.maxViews) {
177
+ const oldest = this.entries.keys().next().value as string | undefined;
178
+ if (oldest === undefined) break;
179
+ this.entries.delete(oldest);
180
+ }
181
+ }
182
+
183
+ reset(viewId?: string): void {
184
+ if (viewId === undefined) this.entries.clear();
185
+ else this.entries.delete(viewId);
186
+ }
187
+
188
+ get(viewId: string): CloudHistory | undefined {
189
+ return this.entries.get(viewId)?.history;
190
+ }
191
+
192
+ dispose(): void {
193
+ this.entries.clear();
194
+ }
195
+ }
196
+
197
+ /** Project one current pixel into the previous cloud history. */
198
+ export function reprojectCloudHistory(
199
+ input: CloudHistoryReprojectionInput,
200
+ historyWeight = 0.9,
201
+ ): CloudHistoryReprojection {
202
+ const width = Math.max(1, input.historySize[0] ?? 1);
203
+ const height = Math.max(1, input.historySize[1] ?? 1);
204
+ const uv: [number, number] = [
205
+ ((input.currentPixel[0] ?? 0) - (input.motion[0] ?? 0)) / width,
206
+ ((input.currentPixel[1] ?? 0) - (input.motion[1] ?? 0)) / height,
207
+ ];
208
+ if (uv[0] < 0 || uv[0] > 1 || uv[1] < 0 || uv[1] > 1) {
209
+ return { accepted: false, historyUv: uv, weight: 0, reason: 'outside' };
210
+ }
211
+ const depthTolerance =
212
+ input.depthTolerance ?? Math.max(0.01, Math.abs(input.currentDepth) * 0.02);
213
+ if (
214
+ !Number.isFinite(input.currentDepth) ||
215
+ !Number.isFinite(input.historyDepth) ||
216
+ Math.abs(input.currentDepth - input.historyDepth) > depthTolerance
217
+ ) {
218
+ return { accepted: false, historyUv: uv, weight: 0, reason: 'depth-disocclusion' };
219
+ }
220
+ return {
221
+ accepted: true,
222
+ historyUv: uv,
223
+ weight: Math.min(0.99, Math.max(0, historyWeight)),
224
+ reason: 'accepted',
225
+ };
226
+ }
@@ -0,0 +1,46 @@
1
+ import { defineComponent, type SchemaOf, type ShapeOf } from '@forgeax/engine-ecs';
2
+ import { err, ok, type Result } from '@forgeax/engine-types';
3
+ import { BarrelDistortionInvalidParameterError } from '../errors/render';
4
+
5
+ /** Camera companion that applies the bounded first-order barrel model. */
6
+ export const BarrelDistortion = defineComponent('BarrelDistortion', {
7
+ strength: { type: 'f32', default: 0 },
8
+ centerX: { type: 'f32', default: 0.5 },
9
+ centerY: { type: 'f32', default: 0.5 },
10
+ });
11
+
12
+ export type BarrelDistortionData = ShapeOf<SchemaOf<typeof BarrelDistortion>>;
13
+
14
+ const DEFAULT_BARREL_DISTORTION: BarrelDistortionData = Object.freeze({
15
+ strength: 0,
16
+ centerX: 0.5,
17
+ centerY: 0.5,
18
+ });
19
+
20
+ function invalid(
21
+ field: 'strength' | 'centerX' | 'centerY',
22
+ value: number,
23
+ expected: string,
24
+ ): BarrelDistortionInvalidParameterError {
25
+ return new BarrelDistortionInvalidParameterError({ field, value, expected });
26
+ }
27
+
28
+ /** Validate and detach camera-owned barrel authoring data. */
29
+ export function validateBarrelDistortionParameters(
30
+ input: Partial<BarrelDistortionData> | undefined,
31
+ ): Result<BarrelDistortionData, BarrelDistortionInvalidParameterError> {
32
+ const value = input ?? {};
33
+ const strength = value.strength ?? DEFAULT_BARREL_DISTORTION.strength;
34
+ const centerX = value.centerX ?? DEFAULT_BARREL_DISTORTION.centerX;
35
+ const centerY = value.centerY ?? DEFAULT_BARREL_DISTORTION.centerY;
36
+ if (!Number.isFinite(strength) || strength < 0 || strength > 0.35) {
37
+ return err(invalid('strength', strength, 'finite and in [0, 0.35]'));
38
+ }
39
+ if (!Number.isFinite(centerX) || centerX < 0 || centerX > 1) {
40
+ return err(invalid('centerX', centerX, 'finite and in [0, 1]'));
41
+ }
42
+ if (!Number.isFinite(centerY) || centerY < 0 || centerY > 1) {
43
+ return err(invalid('centerY', centerY, 'finite and in [0, 1]'));
44
+ }
45
+ return ok(Object.freeze({ strength, centerX, centerY }));
46
+ }
@@ -0,0 +1,47 @@
1
+ import { defineComponent, type SchemaOf, type ShapeOf } from '@forgeax/engine-ecs';
2
+
3
+ /** Closed quality lane for the renderer-owned procedural cloud producer. */
4
+ export type CloudQuality = 'low' | 'medium' | 'high';
5
+
6
+ export const CloudQualityValue = Object.freeze({
7
+ low: 0,
8
+ medium: 1,
9
+ high: 2,
10
+ } as const);
11
+
12
+ /**
13
+ * A single World-authored cloud layer.
14
+ *
15
+ * The component contains only source facts. Cache resolution, optical step
16
+ * counts, temporal history and GPU handles are derived by Render and never
17
+ * written back into ECS.
18
+ */
19
+ export const CloudLayer = defineComponent('CloudLayer', {
20
+ /** Stable integer seed for the periodic 3D density field. */
21
+ seed: { type: 'u32', default: 1337 },
22
+ /** World-space lower edge of the layer, in metres. */
23
+ baseHeight: { type: 'f32', default: 120 },
24
+ /** World-space thickness of the layer, in metres. */
25
+ thickness: { type: 'f32', default: 80 },
26
+ /** Horizontal noise scale, in cycles per metre. */
27
+ scale: { type: 'f32', default: 0.004 },
28
+ /** Coverage threshold in [0, 1]. */
29
+ coverage: { type: 'f32', default: 0.48 },
30
+ /** Extinction multiplier in inverse metres. */
31
+ density: { type: 'f32', default: 1 },
32
+ /** World-space wind velocity in metres per second. */
33
+ wind: { type: 'array<f32, 3>', default: new Float32Array([8, 0, 2]) },
34
+ /** Quality controls cache resolution and bounded ray steps. */
35
+ quality: { type: 'f32', default: CloudQualityValue.medium },
36
+ /** Maximum world-space distance represented by the light-space shadow map. */
37
+ shadowRange: { type: 'f32', default: 512 },
38
+ });
39
+
40
+ export type CloudLayerData = ShapeOf<SchemaOf<typeof CloudLayer>>;
41
+
42
+ export function cloudQualityFromF32(value: number): CloudQuality | undefined {
43
+ if (value === CloudQualityValue.low) return 'low';
44
+ if (value === CloudQualityValue.medium) return 'medium';
45
+ if (value === CloudQualityValue.high) return 'high';
46
+ return undefined;
47
+ }
@@ -1,5 +1,7 @@
1
1
  export * from './atmosphere';
2
+ export * from './barrel-distortion';
2
3
  export * from './camera';
4
+ export * from './cloud-layer';
3
5
  export * from './cube-camera';
4
6
  export * from './depth-of-field';
5
7
  export * from './directional-light';
@@ -1,50 +1,23 @@
1
- // @forgeax/engine-render - renderer-owned large instance association.
2
- //
3
- // The ECS component deliberately carries only a stable collection identity.
4
- // Matrix bytes, revision, capacity, dirty ranges, GPU residency and fallback
5
- // policy belong to InstanceCollectionStore, exposed from the same Renderer.
6
- // This keeps large payloads out of the ECS managed BufferPool while retaining
7
- // ordinary query and entity-lifetime semantics.
8
- //
9
- // Authoring example:
10
- //
11
- // const transforms = new Float32Array(instanceCount * 16);
12
- // for (let index = 0; index < instanceCount; index += 1) {
13
- // const offset = index * 16;
14
- // transforms[offset] = 1;
15
- // transforms[offset + 5] = 1;
16
- // transforms[offset + 10] = 1;
17
- // transforms[offset + 15] = 1;
18
- // }
19
- // const collection = renderer.instances.create({
20
- // transforms,
21
- // }).unwrap();
22
- // world.spawn(
23
- // { component: MeshFilter, data: { assetHandle: HANDLE_CUBE } },
24
- // { component: MeshRenderer, data: {} },
25
- // { component: Instances, data: { collectionId: collection.collectionId } },
26
- // );
27
- //
28
- // Updates stay on the renderer owner and publish one revision:
29
- //
30
- // renderer.instances.update(collection.collectionId, {
31
- // start: 12,
32
- // transforms: patch,
33
- // });
34
- //
35
- // Render extraction snapshots the validated packed column-major matrices once
36
- // per frame. Direct, GPU-driven and fallback lanes consume that same detached
37
- // projection; callers never split one logical collection into ECS chunks.
38
-
39
1
  import { defineComponent } from '@forgeax/engine-ecs';
40
- import type { InstanceCollectionData } from '../instances';
41
2
 
42
- /** Per-entity association with a renderer-owned instance collection. */
3
+ /**
4
+ * World-owned local transforms for one explicit instanced renderable.
5
+ * Packed column-major mat4 values compose as entityWorld * instanceLocal.
6
+ * ECS owns copying, mutation and entity lifetime, including large arrays.
7
+ * Renderer extraction derives its own snapshot and GPU residency; neither
8
+ * authoring nor glTF SceneAsset lowering requires a Renderer identity.
9
+ *
10
+ * @example
11
+ * const transforms = new Float32Array(20_000 * 16);
12
+ * for (let i = 0; i < 20_000; i++) {
13
+ * transforms[i * 16] = transforms[i * 16 + 5] =
14
+ * transforms[i * 16 + 10] = transforms[i * 16 + 15] = 1;
15
+ * }
16
+ * const entity = world.spawn({ component: Instances, data: { transforms } }).unwrap();
17
+ * world.set(entity, Instances, { transforms }).unwrap();
18
+ */
43
19
  export const Instances = defineComponent('Instances', {
44
- collectionId: { type: 'u32', default: 0 },
20
+ transforms: { type: 'array<f32>' },
45
21
  });
46
22
 
47
- /** Type-level hint for the `data` object at the Instances spawn site. */
48
- export type InstancesData = InstanceCollectionData;
49
-
50
- export type { InstanceCollectionId } from '../instances';
23
+ export type InstancesData = { readonly transforms: Float32Array };
@@ -41,7 +41,7 @@
41
41
  // composes per instance:
42
42
  // world_position[i] = entity_world * instances_local[i] * vertex_position
43
43
  // `SpriteInstances.transforms[i*16..i*16+15]` is interpreted as a local-
44
- // space transform under the entity, matching the 3D collection projection.
44
+ // space transform under the entity, exactly like `Instances.transforms`.
45
45
  // Set the entity's `Transform` to identity to make `instances_local[i]`
46
46
  // directly world-space.
47
47
  //
@@ -14,7 +14,7 @@ export type {
14
14
  RhiBackendInstrumentation,
15
15
  RhiBackendPack,
16
16
  } from './assembly/backend-contract';
17
- export { EngineEnvironmentError } from './assembly/backend-contract';
17
+ export { EngineEnvironmentError, loadRhiPack } from './assembly/backend-contract';
18
18
  export type { RendererLegacyHostAdapter } from './assembly/host-contract';
19
19
  export type { BundlerOptions };
20
20
 
@@ -1,3 +1,4 @@
1
+ import type { RenderResourceScope } from '../publication/resource-scope';
1
2
  import { type MeshResidencyLease, MeshResidencyLifetime } from './mesh-residency-lifetime';
2
3
  // @forgeax/engine-runtime - GpuResidencyCache
3
4
  // (feat-20260601-device/gpu-residency-extraction M1; M2 added the deriveRenderData
@@ -37,7 +38,6 @@ import {
37
38
  type MipmapShaderModuleFactory,
38
39
  prepareMipmaps,
39
40
  } from '@forgeax/engine-assets-runtime';
40
- import type { World } from '@forgeax/engine-ecs';
41
41
  import { deriveVertexCount, type VertexLayoutProjection } from '@forgeax/engine-geometry';
42
42
  import { halfFloat } from '@forgeax/engine-math';
43
43
  import {
@@ -288,8 +288,9 @@ function makeImageError<C extends ImageErrorCode>(
288
288
 
289
289
  /** Cube-POD register-relay injected by the wire layer (D-3). */
290
290
  type RegisterCube = (
291
- world: World,
291
+ world: RenderResourceScope,
292
292
  pod: EquirectAsset,
293
+ source: Handle<'EquirectAsset', 'shared'>,
293
294
  ) => Result<Handle<'EquirectAsset', 'shared'>, AssetError>;
294
295
 
295
296
  // feat-20260612-rhi-destroy-renderer-dispose-gpu-lifecycle / M-3 / w11:
@@ -607,16 +608,16 @@ export class GpuResidencyCache {
607
608
  }
608
609
 
609
610
  /**
610
- * Compose a cache key from the raw handle slot and its owning World. The
611
+ * Compose a cache key from the raw handle slot and its owning RenderResourceScope. The
611
612
  * draw-time world index is only a position in one frame's `worlds[]`; it is
612
- * not an asset identity and can be reused by a later World. World objects
613
+ * not an asset identity and can be reused by a later RenderResourceScope. RenderResourceScope objects
613
614
  * therefore receive a renderer-local namespace, while numeric callers keep
614
615
  * the legacy namespace for low-level tests and built-in upload paths.
615
616
  */
616
- private readonly worldNamespaces = new WeakMap<World, number>();
617
+ private readonly worldNamespaces = new WeakMap<RenderResourceScope, number>();
617
618
  private nextWorldNamespace = 1;
618
619
 
619
- private worldKey(slot: number, world: World | number): string | number {
620
+ private worldKey(slot: number, world: RenderResourceScope | number): string | number {
620
621
  if (typeof world === 'number') {
621
622
  return world === 0 ? slot : world * 0x1000000 + slot;
622
623
  }
@@ -809,7 +810,7 @@ export class GpuResidencyCache {
809
810
  */
810
811
  evictTexture(
811
812
  handle: Handle<'TextureAsset', 'shared'>,
812
- worldId: World | number = 0,
813
+ worldId: RenderResourceScope | number = 0,
813
814
  ): { freed: number; errors: RhiError[] } {
814
815
  const id = this.worldKey(handleSlot(handle), worldId);
815
816
  const entry = this.textureGpuHandles.get(id);
@@ -835,7 +836,7 @@ export class GpuResidencyCache {
835
836
 
836
837
  evictMesh(
837
838
  handle: Handle<'MeshAsset', 'shared'>,
838
- worldId: World | number = 0,
839
+ worldId: RenderResourceScope | number = 0,
839
840
  ): { freed: number; errors: RhiError[] } {
840
841
  const id = this.worldKey(Number(handle), worldId);
841
842
  const entry = this.meshGpuHandles.get(id);
@@ -1000,7 +1001,7 @@ export class GpuResidencyCache {
1000
1001
  */
1001
1002
  _getTextureGpuTexture(
1002
1003
  handle: Handle<'TextureAsset', 'shared'>,
1003
- worldId: World | number = 0,
1004
+ worldId: RenderResourceScope | number = 0,
1004
1005
  ): GpuTexture | undefined {
1005
1006
  return this.textureGpuHandles.get(this.worldKey(handleSlot(handle), worldId))?.texture;
1006
1007
  }
@@ -1011,7 +1012,7 @@ export class GpuResidencyCache {
1011
1012
  */
1012
1013
  getTextureGpuView(
1013
1014
  handle: Handle<'TextureAsset', 'shared'>,
1014
- worldId: World | number = 0,
1015
+ worldId: RenderResourceScope | number = 0,
1015
1016
  ): TextureView | undefined {
1016
1017
  return this.textureGpuHandles.get(this.worldKey(handleSlot(handle), worldId))?.view;
1017
1018
  }
@@ -1024,7 +1025,7 @@ export class GpuResidencyCache {
1024
1025
  ensureSamplerResident(
1025
1026
  handle: Handle<'SamplerAsset', 'shared'>,
1026
1027
  pod: SamplerAsset,
1027
- worldId: World | number = 0,
1028
+ worldId: RenderResourceScope | number = 0,
1028
1029
  ): Result<Sampler, RhiError> {
1029
1030
  const key = this.worldKey(handleSlot(handle), worldId);
1030
1031
  const existing = this.samplerGpuHandles.get(key);
@@ -1093,7 +1094,7 @@ export class GpuResidencyCache {
1093
1094
  */
1094
1095
  getMeshGpuHandles(
1095
1096
  handle: Handle<'MeshAsset', 'shared'>,
1096
- worldId: World | number = 0,
1097
+ worldId: RenderResourceScope | number = 0,
1097
1098
  ): MeshGpuHandles | undefined {
1098
1099
  return this.meshGpuHandles.get(this.worldKey(Number(handle), worldId));
1099
1100
  }
@@ -1101,7 +1102,7 @@ export class GpuResidencyCache {
1101
1102
  /** Candidate leases retain the concrete allocation even after cache invalidation. */
1102
1103
  retainMeshResidency(
1103
1104
  handle: Handle<'MeshAsset', 'shared'>,
1104
- worldId: World | number = 0,
1105
+ worldId: RenderResourceScope | number = 0,
1105
1106
  ): MeshResidencyLease | undefined {
1106
1107
  const key = this.worldKey(Number(handle), worldId);
1107
1108
  const entry = this.meshGpuHandles.get(key);
@@ -1114,7 +1115,7 @@ export class GpuResidencyCache {
1114
1115
  }
1115
1116
 
1116
1117
  /** In-place author changes immediately miss the cache; old submissions keep their allocation. */
1117
- invalidateMesh(handle: number, worldId: World | number = 0): void {
1118
+ invalidateMesh(handle: number, worldId: RenderResourceScope | number = 0): void {
1118
1119
  const key = this.worldKey(handle, worldId);
1119
1120
  const entry = this.meshGpuHandles.get(key);
1120
1121
  if (entry !== undefined) this.retireMeshEntry(key, entry);
@@ -1137,18 +1138,18 @@ export class GpuResidencyCache {
1137
1138
  ensureResident(
1138
1139
  handle: Handle<'MeshAsset', 'shared'>,
1139
1140
  pod: TypesMeshAsset,
1140
- worldId?: World | number,
1141
+ worldId?: RenderResourceScope | number,
1141
1142
  lodMeshes?: readonly TypesMeshAsset[],
1142
1143
  ): Result<MeshGpuHandles, RhiError | AssetError | ImageError>;
1143
1144
  ensureResident(
1144
1145
  handle: Handle<'TextureAsset', 'shared'>,
1145
1146
  pod: TextureAsset,
1146
- worldId?: World | number,
1147
+ worldId?: RenderResourceScope | number,
1147
1148
  ): Result<TextureGpuEntry, RhiError | AssetError | ImageError>;
1148
1149
  ensureResident(
1149
1150
  handle: Handle<'MeshAsset', 'shared'> | Handle<'TextureAsset', 'shared'>,
1150
1151
  pod: TypesMeshAsset | TextureAsset,
1151
- worldId: World | number = 0,
1152
+ worldId: RenderResourceScope | number = 0,
1152
1153
  lodMeshes: readonly TypesMeshAsset[] = [],
1153
1154
  ): Result<TextureGpuEntry | MeshGpuHandles, RhiError | AssetError | ImageError> {
1154
1155
  const id = handleSlot(handle);
@@ -1218,17 +1219,17 @@ export class GpuResidencyCache {
1218
1219
  prepareResidentForRecovery(
1219
1220
  handle: Handle<'MeshAsset', 'shared'>,
1220
1221
  pod: TypesMeshAsset,
1221
- worldId?: World | number,
1222
+ worldId?: RenderResourceScope | number,
1222
1223
  ): Result<RecoveryResidencyPreparation, RhiError | AssetError | ImageError>;
1223
1224
  prepareResidentForRecovery(
1224
1225
  handle: Handle<'TextureAsset', 'shared'>,
1225
1226
  pod: TextureAsset,
1226
- worldId?: World | number,
1227
+ worldId?: RenderResourceScope | number,
1227
1228
  ): Result<RecoveryResidencyPreparation, RhiError | AssetError | ImageError>;
1228
1229
  prepareResidentForRecovery(
1229
1230
  handle: Handle<'MeshAsset', 'shared'> | Handle<'TextureAsset', 'shared'>,
1230
1231
  pod: TypesMeshAsset | TextureAsset,
1231
- worldId: World | number = 0,
1232
+ worldId: RenderResourceScope | number = 0,
1232
1233
  ): Result<RecoveryResidencyPreparation, RhiError | AssetError | ImageError> {
1233
1234
  const id = handleSlot(handle);
1234
1235
  if (pod.kind === 'mesh') {
@@ -1316,7 +1317,7 @@ export class GpuResidencyCache {
1316
1317
  handle: Handle<'TextureAsset', 'shared'>,
1317
1318
  pod: TextureAsset,
1318
1319
  decoded: DecodedImage,
1319
- worldId: World | number = 0,
1320
+ worldId: RenderResourceScope | number = 0,
1320
1321
  ): Promise<Result<void, AssetError | ImageError | RhiError>> {
1321
1322
  const device = this.gpuDevice;
1322
1323
  const projected = deriveRenderDataTexture(pod);
@@ -1392,7 +1393,7 @@ export class GpuResidencyCache {
1392
1393
  pod: TextureAsset,
1393
1394
  decoded: DecodedImage,
1394
1395
  renderData: TextureRenderData,
1395
- worldId: World | number = 0,
1396
+ worldId: RenderResourceScope | number = 0,
1396
1397
  ): Result<TextureGpuEntry, AssetError | ImageError | RhiError> {
1397
1398
  const device = this.gpuDevice;
1398
1399
  const prepared = this.prepareTextureUpload(handle, pod, decoded, renderData);
@@ -1654,7 +1655,7 @@ export class GpuResidencyCache {
1654
1655
  * retries by inferring "no entry => try again".
1655
1656
  */
1656
1657
  async _uploadCubemapFromEquirect(
1657
- world: World,
1658
+ world: RenderResourceScope,
1658
1659
  sourceHandle: Handle<'EquirectAsset', 'shared'>,
1659
1660
  sourcePod: EquirectAsset,
1660
1661
  ): Promise<Result<Handle<'EquirectAsset', 'shared'>, AssetError | RhiError>> {
@@ -1999,7 +2000,7 @@ export class GpuResidencyCache {
1999
2000
  view: cubeView,
2000
2001
  faceViews,
2001
2002
  });
2002
- const regResult = registerCube(world, cubeAsset);
2003
+ const regResult = registerCube(world, cubeAsset, sourceHandle);
2003
2004
  if (!regResult.ok) return recordFailed(regResult.error);
2004
2005
  const cubeHandle = regResult.value;
2005
2006
  const cubeId = handleSlot(cubeHandle);
@@ -2252,7 +2253,7 @@ export class GpuResidencyCache {
2252
2253
  handle: Handle<'MeshAsset', 'shared'>,
2253
2254
  newVertices: Float32Array,
2254
2255
  newIndices: Uint16Array,
2255
- worldId: World | number = 0,
2256
+ worldId: RenderResourceScope | number = 0,
2256
2257
  submeshes?: readonly Submesh[],
2257
2258
  ): void {
2258
2259
  const id = this.worldKey(handleSlot(handle), worldId);
@@ -53,6 +53,9 @@ export interface DynamicGeometryCandidate {
53
53
  readonly state: DynamicGeometryCandidateState;
54
54
  }
55
55
 
56
+ /** Record-stage lane that consumed a published dynamic-geometry candidate. */
57
+ export type DynamicGeometryRecordStageLane = 'cpu' | 'gpu' | 'mixed';
58
+
56
59
  /** Receipt that ties candidate publication to the sole Renderer FrameReceipt. */
57
60
  export interface DynamicGeometryReceipt {
58
61
  readonly candidateId: string;
@@ -69,6 +72,8 @@ export interface DynamicGeometryReceipt {
69
72
  };
70
73
  /** Whether the Renderer record stage consumed this candidate for this frame. */
71
74
  readonly recordStageConsumed: boolean;
75
+ /** Lane evidence from the exact submitted record stage, when attached. */
76
+ readonly recordStageLane?: DynamicGeometryRecordStageLane;
72
77
  /** Actual frame fixed step; may be newer than the preparation step. */
73
78
  readonly publicationFixedStep?: number;
74
79
  }
@@ -271,6 +276,9 @@ export interface DynamicGeometryLifecycle {
271
276
  worlds?: readonly object[],
272
277
  fixedStep?: number,
273
278
  canPublish?: (candidate: DynamicGeometryCandidate) => boolean,
279
+ recordStageLane?: (
280
+ candidate: DynamicGeometryCandidate,
281
+ ) => DynamicGeometryRecordStageLane | undefined,
274
282
  ): readonly DynamicGeometryReceipt[];
275
283
  invalidateWorld(world: object, completion?: Promise<unknown>): void;
276
284
  invalidateGeneration(generation: number): void;
@@ -610,7 +618,7 @@ export function createDynamicGeometryLifecycle(
610
618
  meshBytes = Math.max(0, meshBytes - record.candidate.meshBytes);
611
619
  return ok(undefined);
612
620
  },
613
- publishFrame(frame, worlds, fixedStep, canPublish) {
621
+ publishFrame(frame, worlds, fixedStep, canPublish, recordStageLane) {
614
622
  if (disposed || frame.deviceGeneration !== currentGeneration) return [];
615
623
  const receipts: DynamicGeometryReceipt[] = [];
616
624
  for (const record of records.values()) {
@@ -630,6 +638,8 @@ export function createDynamicGeometryLifecycle(
630
638
  continue;
631
639
  }
632
640
  if (canPublish !== undefined && !canPublish(record.candidate)) continue;
641
+ const consumedLane =
642
+ canPublish === undefined ? undefined : recordStageLane?.(record.candidate);
633
643
  record.candidate = Object.freeze({ ...record.candidate, state: 'published' as const });
634
644
  const receipt = Object.freeze({
635
645
  candidateId: record.candidate.candidateId,
@@ -642,6 +652,7 @@ export function createDynamicGeometryLifecycle(
642
652
  frameId: frame.frameId,
643
653
  deviceGeneration: frame.deviceGeneration,
644
654
  recordStageConsumed: canPublish !== undefined,
655
+ ...(consumedLane === undefined ? {} : { recordStageLane: consumedLane }),
645
656
  ...(fixedStep === undefined ? {} : { publicationFixedStep: fixedStep }),
646
657
  frame: Object.freeze({ ...frame }),
647
658
  });