@forgeax/engine-render 0.1.33 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (518) hide show
  1. package/README.md +1010 -124
  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/dynamic-geometry-host.d.ts +4 -1
  11. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  12. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  14. package/dist/assembly/factory.d.ts +1 -1
  15. package/dist/assembly/factory.d.ts.map +1 -1
  16. package/dist/assembly/host-contract.d.ts +3 -3
  17. package/dist/assembly/host-contract.d.ts.map +1 -1
  18. package/dist/assembly/material/assembly.d.ts.map +1 -1
  19. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  20. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  21. package/dist/assembly/material-shader-policy.d.ts +16 -2
  22. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  23. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  24. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  25. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  26. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  27. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  28. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  29. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  30. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  31. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  32. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  33. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  34. package/dist/assembly/renderer-inspection.d.ts +11 -0
  35. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  36. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  37. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  38. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  39. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  40. package/dist/assembly/webgpu-ready.d.ts +1 -1
  41. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  42. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  43. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  44. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  45. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  46. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  47. package/dist/authoring.mjs +1 -1
  48. package/dist/barrel-distortion.d.ts +47 -0
  49. package/dist/barrel-distortion.d.ts.map +1 -0
  50. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  51. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  52. package/dist/{chunk-ZDQWGQW7.mjs → chunk-HEB564WF.mjs} +4 -4
  53. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-HEB564WF.mjs.map} +1 -1
  54. package/dist/{chunk-VOZWDM3L.mjs → chunk-MKDIT2EM.mjs} +1307 -188
  55. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  56. package/dist/{chunk-LEAXOMYJ.mjs → chunk-OCDLEI6I.mjs} +3 -3
  57. package/dist/{chunk-LEAXOMYJ.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  58. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  59. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  60. package/dist/{chunk-3RTCJTH4.mjs → chunk-SHFUFJ5N.mjs} +184 -13
  61. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  62. package/dist/{chunk-OO3DRYK7.mjs → chunk-UI5SFODX.mjs} +176 -96
  63. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  64. package/dist/{chunk-PLAXOOX5.mjs → chunk-UINHLCZA.mjs} +561 -79
  65. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  66. package/dist/{chunk-NB2S7ZRX.mjs → chunk-WEX45HKH.mjs} +127 -386
  67. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  68. package/dist/cloud/density.d.ts +55 -0
  69. package/dist/cloud/density.d.ts.map +1 -0
  70. package/dist/cloud/extract.d.ts +25 -0
  71. package/dist/cloud/extract.d.ts.map +1 -0
  72. package/dist/cloud/feature.d.ts +57 -0
  73. package/dist/cloud/feature.d.ts.map +1 -0
  74. package/dist/cloud/frame-context.d.ts +8 -0
  75. package/dist/cloud/frame-context.d.ts.map +1 -0
  76. package/dist/cloud/inspection.d.ts +59 -0
  77. package/dist/cloud/inspection.d.ts.map +1 -0
  78. package/dist/cloud/optics.d.ts +56 -0
  79. package/dist/cloud/optics.d.ts.map +1 -0
  80. package/dist/cloud/parameters.d.ts +73 -0
  81. package/dist/cloud/parameters.d.ts.map +1 -0
  82. package/dist/cloud/resources.d.ts +60 -0
  83. package/dist/cloud/resources.d.ts.map +1 -0
  84. package/dist/cloud/shadow.d.ts +42 -0
  85. package/dist/cloud/shadow.d.ts.map +1 -0
  86. package/dist/cloud/temporal.d.ts +74 -0
  87. package/dist/cloud/temporal.d.ts.map +1 -0
  88. package/dist/components/barrel-distortion.d.ts +13 -0
  89. package/dist/components/barrel-distortion.d.ts.map +1 -0
  90. package/dist/components/cloud-layer.d.ts +29 -0
  91. package/dist/components/cloud-layer.d.ts.map +1 -0
  92. package/dist/components/index.d.ts +2 -0
  93. package/dist/components/index.d.ts.map +1 -1
  94. package/dist/components/instances.d.ts +20 -6
  95. package/dist/components/instances.d.ts.map +1 -1
  96. package/dist/construct-renderer.d.ts +1 -1
  97. package/dist/construct-renderer.d.ts.map +1 -1
  98. package/dist/construct-renderer.mjs +6759 -2875
  99. package/dist/construct-renderer.mjs.map +1 -1
  100. package/dist/dynamic-geometry.d.ts +5 -1
  101. package/dist/dynamic-geometry.d.ts.map +1 -1
  102. package/dist/errors/cloud.d.ts +59 -0
  103. package/dist/errors/cloud.d.ts.map +1 -0
  104. package/dist/errors/render.d.ts +18 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  107. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  108. package/dist/extract/camera.d.ts.map +1 -1
  109. package/dist/extract/contracts.d.ts +5 -1
  110. package/dist/extract/contracts.d.ts.map +1 -1
  111. package/dist/features/barrel-distortion.d.ts +29 -0
  112. package/dist/features/barrel-distortion.d.ts.map +1 -0
  113. package/dist/features/error-reporting.d.ts +6 -2
  114. package/dist/features/error-reporting.d.ts.map +1 -1
  115. package/dist/features/host.d.ts +10 -0
  116. package/dist/features/host.d.ts.map +1 -1
  117. package/dist/features/plan.d.ts +8 -0
  118. package/dist/features/plan.d.ts.map +1 -1
  119. package/dist/features/render-graph-contribution.d.ts +5 -0
  120. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  121. package/dist/features/render-graph-raster.d.ts +1 -0
  122. package/dist/features/render-graph-raster.d.ts.map +1 -1
  123. package/dist/features/targets.d.ts +2 -0
  124. package/dist/features/targets.d.ts.map +1 -1
  125. package/dist/features/types.d.ts +44 -0
  126. package/dist/features/types.d.ts.map +1 -1
  127. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  128. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  129. package/dist/gpu-dirty-ranges.d.ts +11 -0
  130. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  131. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  132. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  133. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  134. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  135. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  136. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  137. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  138. package/dist/gpu-driven/production-raster.d.ts +47 -3
  139. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  140. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  141. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  142. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  143. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  144. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  145. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  146. package/dist/gpu-scene.d.ts +5 -0
  147. package/dist/gpu-scene.d.ts.map +1 -1
  148. package/dist/hdrp-buffers.d.ts +2 -2
  149. package/dist/hdrp-buffers.d.ts.map +1 -1
  150. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +27 -7
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +258 -8
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +135 -1
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instance-buffer-cache.d.ts +4 -4
  159. package/dist/instance-buffer-cache.d.ts.map +1 -1
  160. package/dist/instances.d.ts +48 -100
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.mjs +7 -7
  163. package/dist/pbr-pipeline.d.ts +19 -1
  164. package/dist/pbr-pipeline.d.ts.map +1 -1
  165. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  166. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  167. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  168. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  169. package/dist/pipeline/standard-output/types.d.ts +4 -2
  170. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  171. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  172. package/dist/pipeline/standard-post.d.ts.map +1 -1
  173. package/dist/pipeline-builder.d.ts +1 -1
  174. package/dist/pipeline-builder.d.ts.map +1 -1
  175. package/dist/plugin.d.ts.map +1 -1
  176. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  177. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  178. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  179. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  180. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  181. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  182. package/dist/record/fold-buckets.d.ts +95 -0
  183. package/dist/record/fold-buckets.d.ts.map +1 -0
  184. package/dist/record/fold-instance-buffer.d.ts +6 -0
  185. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  186. package/dist/record/frame-lighting.d.ts +1 -0
  187. package/dist/record/frame-lighting.d.ts.map +1 -1
  188. package/dist/record/frame-snapshot.d.ts +37 -3
  189. package/dist/record/frame-snapshot.d.ts.map +1 -1
  190. package/dist/record/frame.d.ts +10 -61
  191. package/dist/record/frame.d.ts.map +1 -1
  192. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  193. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  194. package/dist/record/gpu-timing.d.ts +8 -0
  195. package/dist/record/gpu-timing.d.ts.map +1 -1
  196. package/dist/record/main-pass-geometry.d.ts +21 -5
  197. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  198. package/dist/record/main-pass-material.d.ts +7 -1
  199. package/dist/record/main-pass-material.d.ts.map +1 -1
  200. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  201. package/dist/record/main-pass.d.ts +13 -2
  202. package/dist/record/main-pass.d.ts.map +1 -1
  203. package/dist/record/motion-blur-receipt.d.ts +11 -0
  204. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  205. package/dist/record/probe-blend-buffer.d.ts +16 -0
  206. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  207. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  208. package/dist/record/render-context.d.ts +22 -3
  209. package/dist/record/render-context.d.ts.map +1 -1
  210. package/dist/record/shadow-pass.d.ts +2 -0
  211. package/dist/record/shadow-pass.d.ts.map +1 -1
  212. package/dist/record/skybox-post-pass.d.ts +1 -1
  213. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  214. package/dist/record/typed-frame-graph.d.ts +22 -2
  215. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  216. package/dist/record/view-ubo.d.ts +11 -3
  217. package/dist/record/view-ubo.d.ts.map +1 -1
  218. package/dist/record/volume-params.d.ts +9 -0
  219. package/dist/record/volume-params.d.ts.map +1 -0
  220. package/dist/recovery/render-system-candidate.d.ts +10 -0
  221. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  222. package/dist/reflection/record-owner.d.ts.map +1 -1
  223. package/dist/render-contract.d.ts +42 -4
  224. package/dist/render-contract.d.ts.map +1 -1
  225. package/dist/render-graph-primitives.d.ts.map +1 -1
  226. package/dist/render-pipeline.d.ts +103 -2
  227. package/dist/render-pipeline.d.ts.map +1 -1
  228. package/dist/render-system-extract-tail.d.ts +3 -2
  229. package/dist/render-system-extract-tail.d.ts.map +1 -1
  230. package/dist/render-system-extract.d.ts +16 -9
  231. package/dist/render-system-extract.d.ts.map +1 -1
  232. package/dist/render-system-presentation.d.ts +23 -0
  233. package/dist/render-system-presentation.d.ts.map +1 -0
  234. package/dist/render-system-producer-roots.d.ts +10 -0
  235. package/dist/render-system-producer-roots.d.ts.map +1 -0
  236. package/dist/render-system-residency.d.ts +12 -0
  237. package/dist/render-system-residency.d.ts.map +1 -0
  238. package/dist/render-system.d.ts +19 -14
  239. package/dist/render-system.d.ts.map +1 -1
  240. package/dist/scene/probe-blend.d.ts +27 -0
  241. package/dist/scene/probe-blend.d.ts.map +1 -1
  242. package/dist/scene/render-scene.d.ts +12 -5
  243. package/dist/scene/render-scene.d.ts.map +1 -1
  244. package/dist/ssao-buffers.d.ts +9 -0
  245. package/dist/ssao-buffers.d.ts.map +1 -1
  246. package/dist/surface/dynamic-input.d.ts +133 -0
  247. package/dist/surface/dynamic-input.d.ts.map +1 -0
  248. package/dist/surface/gpu-driven.d.ts +41 -0
  249. package/dist/surface/gpu-driven.d.ts.map +1 -0
  250. package/dist/surface/submission-observation.d.ts +136 -0
  251. package/dist/surface/submission-observation.d.ts.map +1 -0
  252. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  253. package/dist/temporal/gpu.d.ts +13 -1
  254. package/dist/temporal/gpu.d.ts.map +1 -1
  255. package/dist/temporal/index.mjs +5 -5
  256. package/dist/temporal/inspection.d.ts.map +1 -1
  257. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  258. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  259. package/dist/transmission/single-layer-medium.d.ts +89 -0
  260. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  261. package/dist/typed-render-graph-primitives.d.ts +14 -2
  262. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  263. package/dist/volume/component.d.ts +9 -4
  264. package/dist/volume/component.d.ts.map +1 -1
  265. package/dist/volume/extract.d.ts +1 -1
  266. package/dist/volume/extract.d.ts.map +1 -1
  267. package/dist/volume/inspection.d.ts +2 -0
  268. package/dist/volume/inspection.d.ts.map +1 -1
  269. package/dist/volume/passes.d.ts +4 -1
  270. package/dist/volume/passes.d.ts.map +1 -1
  271. package/dist/volume/resources.d.ts.map +1 -1
  272. package/package.json +22 -21
  273. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  274. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  275. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  276. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  277. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  278. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  279. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  280. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  281. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  282. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  283. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  284. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  285. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  286. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  287. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  288. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  289. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  290. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  291. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  292. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  293. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  294. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  295. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  296. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  297. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  298. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  299. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  300. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  301. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  302. package/src/__tests__/instances-store.unit.test.ts +97 -305
  303. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  304. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  305. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  306. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  307. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  308. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  309. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  310. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  311. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  312. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  313. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  314. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  315. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  316. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  317. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  318. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  319. package/src/__tests__/render-error-code-owner.test-d.ts +7 -0
  320. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  321. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  322. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  323. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  324. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  325. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  326. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  327. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  328. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  329. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  330. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  331. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  332. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  333. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  334. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  335. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  336. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  337. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  338. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  339. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  340. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  341. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  342. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  343. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  344. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  345. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  346. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  347. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  348. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  349. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  350. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  351. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  352. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  353. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  354. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  355. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  356. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  357. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  358. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  359. package/src/assembly/backend-contract.ts +30 -0
  360. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  361. package/src/assembly/canvas-draw-guard.ts +11 -0
  362. package/src/assembly/cloud-shadow-entry.ts +22 -0
  363. package/src/assembly/dynamic-geometry-host.ts +65 -37
  364. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  365. package/src/assembly/factory.ts +2 -30
  366. package/src/assembly/host-contract.ts +3 -3
  367. package/src/assembly/material/assembly.ts +25 -13
  368. package/src/assembly/material/pipeline-helpers.ts +53 -12
  369. package/src/assembly/material-shader-policy.ts +55 -0
  370. package/src/assembly/material-shader-prewarm.ts +21 -10
  371. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  372. package/src/assembly/recovery/renderer-recover.ts +41 -18
  373. package/src/assembly/render-feature-post-processes.ts +54 -0
  374. package/src/assembly/renderer-facade.ts +4 -1
  375. package/src/assembly/renderer-feature-inspection.ts +8 -2
  376. package/src/assembly/renderer-frame-transaction.ts +23 -0
  377. package/src/assembly/renderer-inspection.ts +28 -0
  378. package/src/assembly/skin-palette-owner.ts +1 -1
  379. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  380. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  381. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  382. package/src/assembly/webgpu-ready.ts +115 -61
  383. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  384. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  385. package/src/assembly/webgpu-renderer.ts +214 -252
  386. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  387. package/src/barrel-distortion.ts +247 -0
  388. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  389. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  390. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  391. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  392. package/src/cloud/density.ts +600 -0
  393. package/src/cloud/extract.ts +110 -0
  394. package/src/cloud/feature.ts +1810 -0
  395. package/src/cloud/frame-context.ts +42 -0
  396. package/src/cloud/inspection.ts +130 -0
  397. package/src/cloud/optics.ts +285 -0
  398. package/src/cloud/parameters.ts +255 -0
  399. package/src/cloud/resources.ts +122 -0
  400. package/src/cloud/shadow.ts +167 -0
  401. package/src/cloud/temporal.ts +226 -0
  402. package/src/components/barrel-distortion.ts +46 -0
  403. package/src/components/cloud-layer.ts +47 -0
  404. package/src/components/index.ts +2 -0
  405. package/src/components/instances.ts +18 -45
  406. package/src/components/sprite-instances.ts +1 -1
  407. package/src/construct-renderer.ts +1 -1
  408. package/src/dynamic-geometry.ts +12 -1
  409. package/src/errors/cloud.ts +103 -0
  410. package/src/errors/render.ts +44 -7
  411. package/src/examples/single-layer-medium-surface.ts +59 -0
  412. package/src/extract/camera.ts +15 -1
  413. package/src/extract/contracts.ts +5 -0
  414. package/src/features/barrel-distortion.ts +172 -0
  415. package/src/features/error-reporting.ts +26 -6
  416. package/src/features/host.ts +115 -14
  417. package/src/features/plan.ts +8 -0
  418. package/src/features/render-graph-contribution.ts +9 -0
  419. package/src/features/render-graph-raster.ts +45 -3
  420. package/src/features/targets.ts +66 -0
  421. package/src/features/types.ts +47 -0
  422. package/src/fullscreen-post-process-pass.ts +41 -9
  423. package/src/gpu-dirty-ranges.ts +48 -0
  424. package/src/gpu-driven/batch-topology.ts +53 -0
  425. package/src/gpu-driven/material-artifacts.ts +33 -25
  426. package/src/gpu-driven/prepared-draw.ts +12 -4
  427. package/src/gpu-driven/production-raster-material.ts +1894 -0
  428. package/src/gpu-driven/production-raster.ts +825 -784
  429. package/src/gpu-driven/resource-allocation.ts +142 -0
  430. package/src/gpu-driven/shadow-ownership.ts +71 -0
  431. package/src/gpu-driven/view-gpu.ts +164 -10
  432. package/src/gpu-scene.ts +75 -84
  433. package/src/hdrp-buffers.ts +4 -3
  434. package/src/ibl/skylight-bind-group.ts +49 -7
  435. package/src/index.ts +196 -9
  436. package/src/inspection-types.ts +162 -0
  437. package/src/instance-buffer-cache.ts +4 -4
  438. package/src/instances.ts +149 -569
  439. package/src/pbr-pipeline.ts +219 -13
  440. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  441. package/src/pipeline/standard-forward-lane.ts +313 -57
  442. package/src/pipeline/standard-output/graph.ts +8 -2
  443. package/src/pipeline/standard-output/types.ts +12 -1
  444. package/src/pipeline/standard-pipeline.ts +291 -18
  445. package/src/pipeline/standard-post.ts +90 -24
  446. package/src/pipeline-builder.ts +1 -1
  447. package/src/plugin.ts +4 -0
  448. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  449. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  450. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  451. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  452. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  453. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  454. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  455. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  456. package/src/record/barrel-distortion-frame.ts +110 -0
  457. package/src/record/dynamic-geometry-consumption.ts +39 -9
  458. package/src/record/fold-buckets.ts +852 -0
  459. package/src/record/fold-instance-buffer.ts +51 -0
  460. package/src/record/frame-lighting.ts +36 -2
  461. package/src/record/frame-snapshot.ts +39 -3
  462. package/src/record/frame.ts +217 -1084
  463. package/src/record/gpu-draw-receipts.ts +38 -0
  464. package/src/record/gpu-timing.ts +48 -5
  465. package/src/record/main-pass-geometry.ts +251 -82
  466. package/src/record/main-pass-material.ts +66 -4
  467. package/src/record/main-pass-sprite-draws.ts +7 -65
  468. package/src/record/main-pass.ts +156 -20
  469. package/src/record/motion-blur-receipt.ts +91 -0
  470. package/src/record/probe-blend-buffer.ts +180 -0
  471. package/src/record/recovery-pipeline.ts +35 -3
  472. package/src/record/render-context.ts +39 -3
  473. package/src/record/shadow-pass.ts +30 -1
  474. package/src/record/skybox-post-pass.ts +28 -4
  475. package/src/record/typed-frame-graph.ts +770 -134
  476. package/src/record/view-ubo.ts +26 -3
  477. package/src/record/volume-params.ts +225 -0
  478. package/src/recovery/render-system-candidate.ts +235 -42
  479. package/src/reflection/record-owner.ts +7 -3
  480. package/src/render-contract.ts +48 -4
  481. package/src/render-graph-primitives.ts +7 -1
  482. package/src/render-pipeline.ts +130 -0
  483. package/src/render-system-extract-tail.ts +57 -61
  484. package/src/render-system-extract.ts +74 -76
  485. package/src/render-system-presentation.ts +56 -0
  486. package/src/render-system-producer-roots.ts +96 -0
  487. package/src/render-system-residency.ts +159 -0
  488. package/src/render-system.ts +347 -363
  489. package/src/scene/probe-blend.ts +96 -4
  490. package/src/scene/render-scene.ts +349 -280
  491. package/src/ssao-buffers.ts +95 -2
  492. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  493. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  494. package/src/surface/dynamic-input.ts +658 -0
  495. package/src/surface/gpu-driven.ts +147 -0
  496. package/src/surface/submission-observation.ts +517 -0
  497. package/src/systems/skin-palette-allocator.ts +4 -1
  498. package/src/temporal/gpu.ts +101 -17
  499. package/src/temporal/inspection.ts +7 -1
  500. package/src/temporal/standard-scene-data.ts +5 -0
  501. package/src/temporal/target-coverage-attachment.ts +4 -0
  502. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  503. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  504. package/src/transmission/single-layer-medium.ts +322 -0
  505. package/src/typed-render-graph-primitives.ts +70 -2
  506. package/src/volume/component.ts +10 -9
  507. package/src/volume/extract.ts +11 -5
  508. package/src/volume/inspection.ts +3 -0
  509. package/src/volume/passes.ts +87 -4
  510. package/src/volume/resources.ts +2 -1
  511. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  512. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  513. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  514. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  515. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  516. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  517. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  518. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -1,38 +1,18 @@
1
1
  import { projectCaptureScene } from './capture/scene-projection';
2
2
  import type { RenderSceneBounds } from './scene/render-scene-types';
3
- // @forgeax/engine-runtime - RenderSystem main entry (D-S2 three-stage Extract ->
4
- // Prepare -> Record + 4-tier error fan-out).
5
- //
6
- // Engine-internal phase: NOT registered to World schedule (AC-09);
7
- // `Renderer.draw([world], { cameraOwner: 0, resourceOwner: 0 })` invokes once per frame. See `Renderer` JSDoc in
8
- // `./render-contract.ts` for the public error/frame contract and AGENTS.md
9
- // "ECS render bridge" section for the AI-user-facing contract.
10
- //
11
- // Stage carve-out (review round 1 finding #3 - 505 line cap fallback):
12
- // - render-system.ts (this file) types + orchestration
13
- // - render-system-extract.ts Extract ECS query phase + snapshot helpers
14
- // - render-system-record.ts Prepare + Record GPU phase + matrix helpers
15
- //
16
3
  // @forgeax/engine-math is referenced through render-system-record.ts which builds
17
4
  // view/proj matrices and worldFromLocal via `mat4.compose / .multiply /
18
5
  // .invert` (charter proposition 5: no math reinvention; render-system.test.ts
19
6
  // asserts `/@forgeax\/engine-math/` shows up in render-system.ts source).
20
7
 
21
- import { numMipLevels, resolveAssetHandle } from '@forgeax/engine-assets-runtime';
8
+ import { numMipLevels } from '@forgeax/engine-assets-runtime';
22
9
  import { Time, type World } from '@forgeax/engine-ecs';
23
10
  import type { RenderReadLease } from '@forgeax/engine-ecs/projection';
24
11
  import type { RecorderSession } from '@forgeax/engine-profiler';
25
12
  import type { CompiledRenderGraphInfo } from '@forgeax/engine-render-graph';
26
13
  import type { BindGroupLayout, Buffer, RenderPipeline, RhiDevice } from '@forgeax/engine-rhi';
27
14
  import { err, ok, type Result, RhiError } from '@forgeax/engine-rhi';
28
- import {
29
- deriveTextureLayout,
30
- type MaterialAsset,
31
- type RenderPipelineAsset,
32
- type SamplerAsset,
33
- type TextureAsset,
34
- toShared,
35
- } from '@forgeax/engine-types';
15
+ import { type RenderPipelineAsset, toShared } from '@forgeax/engine-types';
36
16
  import {
37
17
  type DirectionalShadowInspectionSource,
38
18
  directionalShadowProfileFromQuality,
@@ -40,7 +20,9 @@ import {
40
20
  } from './assembly/directional-shadow-inspection';
41
21
  import { createGpuDrivenOwner } from './assembly/gpu-driven-owner';
42
22
  import { standardBloomAdmitted } from './bloom-admission';
23
+ import { createCloudFeatureFrameContext, createCloudFeatureView } from './cloud/frame-context';
43
24
  import { createClusterBinScratch } from './cluster-binner';
25
+ import type { DynamicGeometryRecordStageLane } from './dynamic-geometry';
44
26
  import { EnvironmentLifecycle } from './environment/lifecycle';
45
27
  import {
46
28
  type ObservationUnavailableError,
@@ -49,6 +31,7 @@ import {
49
31
  } from './errors/render';
50
32
  import { projectDepthOfFieldInspection } from './features/depth-of-field/depth-of-field-inspection';
51
33
  import { resolveDepthOfFieldFrameParams } from './features/depth-of-field/depth-of-field-params';
34
+ import type { PendingRenderFeatureErrorReport } from './features/error-reporting';
52
35
  import { reportPendingRenderFeatureErrors } from './features/error-reporting';
53
36
  import {
54
37
  type RenderFeaturePreparedGraphicsResolverInput,
@@ -83,6 +66,7 @@ import {
83
66
  postProcessShaderPipelineLabel,
84
67
  } from './fullscreen-post-process-pass';
85
68
  import type {
69
+ BarrelDistortionInspection,
86
70
  BloomInspection,
87
71
  DepthOfFieldInspection,
88
72
  DirectionalShadowInspection,
@@ -125,11 +109,7 @@ import {
125
109
  } from './pipeline/standard-output/resources';
126
110
  import type { PointsLinesRetainedSnapshot } from './points-lines/snapshot';
127
111
  import { StandardPointsLinesOwner } from './points-lines/standard-owner';
128
- import {
129
- createRenderSystemRecovery,
130
- materialSamplerHandles,
131
- materialTextureHandles,
132
- } from './recovery/render-system-candidate';
112
+ import { createRenderSystemRecovery } from './recovery/render-system-candidate';
133
113
 
134
114
  export { materialTextureHandlesForResidency } from './recovery/render-system-candidate';
135
115
 
@@ -169,9 +149,10 @@ import { inspectVolumetricFog } from './volume/inspection';
169
149
 
170
150
  export type { RenderSceneInspection } from './inspection-types';
171
151
 
152
+ import type { BarrelDistortionMapping } from './barrel-distortion';
172
153
  import { createCubeCaptureScheduler } from './capture/scheduler';
173
154
  import type { EnvironmentInspection } from './environment/inspection';
174
- import { gpuDrivenShadowDrawKey } from './extract/gpu-driven';
155
+ import { rebaseShadowCasterOwnership } from './gpu-driven/shadow-ownership';
175
156
  import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from './gpu-usage';
176
157
  import { resetHdrpBuffers } from './hdrp-buffers';
177
158
  import type { SkylightBindGroupResources } from './ibl/skylight-bind-group';
@@ -181,11 +162,9 @@ import {
181
162
  disposeTransientInstanceBuffers,
182
163
  } from './instance-buffer-cache';
183
164
  import type { InstanceCollectionInspection } from './instances';
184
- import { InstanceCollectionStore } from './instances';
165
+ import { InstanceProjectionStore } from './instances';
185
166
  import {
186
167
  type MeshMaterialBindingObservation,
187
- type MeshMaterialBindingPreparationFailure,
188
- type MeshMaterialBindingResidency,
189
168
  projectMeshMaterialBindingObservation,
190
169
  } from './mesh-material-bindings';
191
170
  import type { StandardLightingInspection } from './pipeline/standard-lighting/inspection';
@@ -198,6 +177,10 @@ import {
198
177
  createPreparedGraphicsResolver,
199
178
  type PreparedGraphicsResolver,
200
179
  } from './prepare/prepared-graphics-resolver';
180
+ import {
181
+ inspectBarrelDistortionState,
182
+ resetBarrelDistortionGraphState,
183
+ } from './record/barrel-distortion-frame';
201
184
  import {
202
185
  type CubeCaptureFrameInput,
203
186
  type FrameObservation,
@@ -213,6 +196,7 @@ import type {
213
196
  RenderFrameState,
214
197
  } from './record/frame-snapshot';
215
198
  import { getTextureIdentity, worldEntityKey } from './record/frame-snapshot';
199
+ import type { RenderableDrawReceipt } from './record/gpu-draw-receipts';
216
200
  import type { GpuPassTimingReason } from './record/gpu-pass-timing/errors';
217
201
  import type {
218
202
  GpuPassTimingCapture,
@@ -230,34 +214,39 @@ import type { PipelineState, RenderSystemInternals } from './record/render-conte
230
214
  import type { CubeCaptureGraphState } from './record/typed-frame-graph';
231
215
  import {
232
216
  getRenderFeatureGraphInspection,
217
+ inspectRenderGraphGenerationAllocation,
233
218
  type RenderFeatureGraphCandidate,
234
219
  recordRenderFeatureCandidate,
235
220
  resetRenderFeatureGraphState,
221
+ retire as retireCompiledGraph,
222
+ settleBarrelDistortionGraphCandidate,
236
223
  settleDepthOfFieldGraphCandidate,
237
224
  settleVolumetricFogGraphCandidate,
238
225
  } from './record/typed-frame-graph';
239
226
  import {
240
227
  type CameraSnapshot,
241
228
  type DrawOwnerOptions,
229
+ type FramePresentation,
242
230
  RENDER_PHASE_CATALOG,
243
231
  type RenderPhase,
244
232
  type RenderPhaseSkipReason,
245
233
  type RenderRecordPhase,
246
234
  } from './render-contract';
247
- import type {
248
- DispatchEntry,
249
- ExtractedLights,
250
- MaterialSnapshot,
251
- RenderableSnapshot,
252
- ShadowCasterMembership,
253
- } from './render-system-extract';
235
+ import type { DispatchEntry, ExtractedLights, RenderableSnapshot } from './render-system-extract';
254
236
  import { extractFrames } from './render-system-extract';
237
+ import { projectFramePresentation } from './render-system-presentation';
238
+ import {
239
+ createRendererProducerRootMatrix,
240
+ type RendererProducerRoot,
241
+ } from './render-system-producer-roots';
255
242
  import {
256
243
  canonicalizeWorldComposition,
257
244
  createLodWorldInspections,
258
245
  } from './render-system-projections';
246
+ import { observeMaterialResidency } from './render-system-residency';
259
247
  import { PersistentRenderScene } from './scene/render-scene';
260
248
  import { inspectLodOcclusion } from './scene/visibility/inspection';
249
+ import { resetSsaoResources } from './ssao-buffers';
261
250
  import { resolveSsaoParameters } from './ssao-config';
262
251
  import {
263
252
  projectSsrDependencies,
@@ -266,6 +255,8 @@ import {
266
255
  zeroSsrAdmissionWork,
267
256
  } from './ssr/admission';
268
257
  import { projectSsrSpatialInspection } from './ssr/inspection';
258
+ import type { SurfaceDynamicInputFrame } from './surface/dynamic-input';
259
+ import { SurfaceSubmissionObservationOwner } from './surface/submission-observation';
269
260
  import { sortTransparentDispatch } from './systems/transparent-dispatch';
270
261
  import type { RenderTarget } from './targets/contracts';
271
262
  import { createTemporalFrameTransaction, type TemporalFrame } from './temporal/frame';
@@ -283,73 +274,6 @@ import {
283
274
  inspectTransmissionFromAdmission,
284
275
  } from './transmission/inspection';
285
276
 
286
- const WORLD_ENTITY_KEY_STRIDE = 4294967296;
287
-
288
- /**
289
- * Extract emits world/entity keys in the transient `worlds[]` index domain,
290
- * while PersistentRenderScene owns stable renderer-local World keys for the
291
- * retained GPU scene. Rebase ShadowCaster ownership at this orchestration
292
- * boundary before both GPU projection and CPU residual recording consume it.
293
- */
294
- function rebaseShadowCasterOwnership(
295
- worlds: readonly World[],
296
- stableWorldKeys: readonly number[],
297
- entityKeys: ReadonlySet<number>,
298
- drawKeys: ReadonlySet<string>,
299
- membership: readonly ShadowCasterMembership[] | undefined,
300
- ): {
301
- readonly entityKeys: ReadonlySet<number>;
302
- readonly drawKeys: ReadonlySet<string>;
303
- readonly membership: readonly ShadowCasterMembership[] | undefined;
304
- } {
305
- const rebaseWorldEntity = (composite: number): number => {
306
- const transientWorldId = Math.floor(composite / WORLD_ENTITY_KEY_STRIDE);
307
- if (
308
- !Number.isInteger(transientWorldId) ||
309
- transientWorldId < 0 ||
310
- transientWorldId >= worlds.length
311
- ) {
312
- return composite;
313
- }
314
- const entityKey = composite - transientWorldId * WORLD_ENTITY_KEY_STRIDE;
315
- return worldEntityKey(stableWorldKeys[transientWorldId] ?? transientWorldId, entityKey);
316
- };
317
-
318
- const stableMembership =
319
- membership === undefined
320
- ? undefined
321
- : membership.map((entry) => ({
322
- ...entry,
323
- worldEntity: rebaseWorldEntity(entry.worldEntity),
324
- }));
325
- const stableDrawKeys =
326
- stableMembership === undefined
327
- ? new Set(
328
- [...drawKeys].map((key) => {
329
- const parts = key.split(':');
330
- if (parts.length !== 4) return key;
331
- const transientWorldEntity = Number(parts[0]);
332
- if (!Number.isFinite(transientWorldEntity)) return key;
333
- return `${rebaseWorldEntity(transientWorldEntity)}:${parts[1]}:${parts[2]}:${parts[3]}`;
334
- }),
335
- )
336
- : new Set(
337
- stableMembership.map((entry) =>
338
- gpuDrivenShadowDrawKey(
339
- entry.worldEntity,
340
- entry.materialHandle,
341
- entry.drawItemIndex,
342
- entry.passIndex,
343
- ),
344
- ),
345
- );
346
- return {
347
- entityKeys: new Set([...entityKeys].map(rebaseWorldEntity)),
348
- drawKeys: stableDrawKeys,
349
- membership: stableMembership,
350
- };
351
- }
352
-
353
277
  type TimingSessionHost = RenderSystemInternals & {
354
278
  gpuPassTimingSession?: GpuPassTimingSession | undefined;
355
279
  gpuPassTimingCapture?: GpuPassTimingCapture | undefined;
@@ -386,102 +310,11 @@ export {
386
310
  selectSwapChainFormat,
387
311
  } from './record/render-context';
388
312
 
389
- export type RendererProducerRootKind =
390
- | 'backend-surface'
391
- | 'shader-material-pipeline'
392
- | 'mesh-texture-sampler'
393
- | 'render-scene'
394
- | 'gpu-driven'
395
- | 'feature'
396
- | 'external-source'
397
- | 'render-graph'
398
- | 'target-history'
399
- | 'observation-lease';
400
-
401
- export interface RendererProducerRoot {
402
- readonly kind: RendererProducerRootKind;
403
- readonly owner: string;
404
- readonly candidateScope: 'device-scope';
405
- readonly visibility: 'visible-workset' | 'non-visible-lazy';
406
- readonly disabledWork: 'zero' | 'lazy';
407
- }
408
-
409
- const PRODUCER_ROOT_MATRIX: readonly RendererProducerRoot[] = Object.freeze([
410
- {
411
- kind: 'backend-surface',
412
- owner: 'backend-surface-owner',
413
- candidateScope: 'device-scope',
414
- visibility: 'visible-workset',
415
- disabledWork: 'zero',
416
- },
417
- {
418
- kind: 'shader-material-pipeline',
419
- owner: 'shader-material-pipeline-owner',
420
- candidateScope: 'device-scope',
421
- visibility: 'visible-workset',
422
- disabledWork: 'zero',
423
- },
424
- {
425
- kind: 'mesh-texture-sampler',
426
- owner: 'gpu-residency',
427
- candidateScope: 'device-scope',
428
- visibility: 'visible-workset',
429
- disabledWork: 'lazy',
430
- },
431
- {
432
- kind: 'render-scene',
433
- owner: 'persistent-render-scene',
434
- candidateScope: 'device-scope',
435
- visibility: 'visible-workset',
436
- disabledWork: 'zero',
437
- },
438
- {
439
- kind: 'gpu-driven',
440
- owner: 'gpu-driven-production',
441
- candidateScope: 'device-scope',
442
- visibility: 'visible-workset',
443
- disabledWork: 'zero',
444
- },
445
- {
446
- kind: 'feature',
447
- owner: 'render-feature-host',
448
- candidateScope: 'device-scope',
449
- visibility: 'visible-workset',
450
- disabledWork: 'lazy',
451
- },
452
- {
453
- kind: 'external-source',
454
- owner: 'external-source-owner',
455
- candidateScope: 'device-scope',
456
- visibility: 'non-visible-lazy',
457
- disabledWork: 'zero',
458
- },
459
- {
460
- kind: 'render-graph',
461
- owner: 'typed-frame-graph',
462
- candidateScope: 'device-scope',
463
- visibility: 'visible-workset',
464
- disabledWork: 'zero',
465
- },
466
- {
467
- kind: 'target-history',
468
- owner: 'temporal-target-owner',
469
- candidateScope: 'device-scope',
470
- visibility: 'visible-workset',
471
- disabledWork: 'zero',
472
- },
473
- {
474
- kind: 'observation-lease',
475
- owner: 'render-observation-owner',
476
- candidateScope: 'device-scope',
477
- visibility: 'non-visible-lazy',
478
- disabledWork: 'zero',
479
- },
480
- ]);
481
-
482
- export function createRendererProducerRootMatrix(): readonly RendererProducerRoot[] {
483
- return PRODUCER_ROOT_MATRIX;
484
- }
313
+ export type {
314
+ RendererProducerRoot,
315
+ RendererProducerRootKind,
316
+ } from './render-system-producer-roots';
317
+ export { createRendererProducerRootMatrix } from './render-system-producer-roots';
485
318
 
486
319
  /**
487
320
  * Production-owned recovery facts. These values are projections of the live
@@ -520,6 +353,8 @@ export interface RecoveryProductionEvidence {
520
353
  */
521
354
  export interface RenderSystem {
522
355
  bounds(world: World, entity: number): RenderSceneBounds | undefined;
356
+ /** Publish one renderer-owned read-only Surface dynamic page for the next frame. */
357
+ setSurfaceDynamicInput(frame: SurfaceDynamicInputFrame | undefined): void;
523
358
  /** Complete explicit SSR capability preparation before drawing a device generation. */
524
359
  initializeSsr(device?: RhiDevice): Promise<void>;
525
360
  /** Returns true only when this invocation reached queue submission. */
@@ -535,6 +370,11 @@ export interface RenderSystem {
535
370
  * barrier; ECS component presence alone is not a draw receipt.
536
371
  */
537
372
  isDynamicGeometryConsumed(world: World, entity: number, meshHandle: number | undefined): boolean;
373
+ dynamicGeometryRecordStageLane(
374
+ world: World,
375
+ entity: number,
376
+ meshHandle: number | undefined,
377
+ ): DynamicGeometryRecordStageLane | undefined;
538
378
  invalidateGeometryHistory(): void;
539
379
  /** Prepare a detached graph candidate without entering the frame record path. */
540
380
  prepareRecoveryGraphCandidate(
@@ -568,8 +408,6 @@ export interface RenderSystem {
568
408
  readonly pipelineDispatchCounts: {
569
409
  readonly unlit: number;
570
410
  };
571
- /** Renderer-owned source for explicit large instance collections. */
572
- readonly instances: InstanceCollectionStore;
573
411
  /** Detached residency and upload facts for explicit instance collections. */
574
412
  readonly instanceCollectionsInspection: readonly InstanceCollectionInspection[];
575
413
  /**
@@ -588,6 +426,8 @@ export interface RenderSystem {
588
426
  readonly ssr: SsrSpatialInspection;
589
427
  /** Producer completion fence included in the public FrameReceipt. */
590
428
  readonly reflectionFallbackCompletion: Promise<void> | undefined;
429
+ /** Presentation readiness derived from the producer facts used by draw(). */
430
+ readonly presentation: FramePresentation;
591
431
  /** True while a progressive CubeCamera candidate still owns unfinished faces. */
592
432
  isCubeCapturePending(target: RenderTarget): boolean;
593
433
  readonly environment: EnvironmentInspection;
@@ -630,8 +470,14 @@ export interface RenderSystem {
630
470
  readonly perFramePassNames: readonly string[];
631
471
  /** Camera antialias mode for the last successfully submitted frame. */
632
472
  readonly lastSuccessfulCameraAntialias: CameraSnapshot['antialias'] | undefined;
473
+ /** Effective output mapping for the last successfully submitted camera. */
474
+ readonly lastSuccessfulBarrelDistortion: BarrelDistortionMapping | undefined;
475
+ /** Detached accepted/LKG projection for Renderer.inspect(). */
476
+ readonly barrelDistortionInspection: BarrelDistortionInspection;
633
477
  /** Detached compiled-graph facts used by the renderer inspection owner. */
634
478
  readonly perFrameGraphInfo: CompiledRenderGraphInfo | undefined;
479
+ /** Detached allocation facts across active, candidate, and retiring graphs. */
480
+ readonly renderGraphGenerationAllocation: import('@forgeax/engine-render-graph').RenderGraphGenerationAllocationInspection;
635
481
  /** Detached feature signature/compile/lifetime counters. */
636
482
  readonly featureGraphInspection: import('./inspection-types').RenderFeatureGraphInspection;
637
483
  /** Detached material texture-source probe counters from the last extract. */
@@ -751,149 +597,6 @@ function makePreparedPipelinePendingError(): RhiError {
751
597
  });
752
598
  }
753
599
 
754
- function preparationFailureFrom(error: unknown): MeshMaterialBindingPreparationFailure | undefined {
755
- if (typeof error !== 'object' || error === null) return undefined;
756
- const value = error as {
757
- readonly code?: unknown;
758
- readonly expected?: unknown;
759
- readonly hint?: unknown;
760
- readonly detail?: unknown;
761
- };
762
- if (
763
- typeof value.code !== 'string' ||
764
- typeof value.expected !== 'string' ||
765
- typeof value.hint !== 'string'
766
- ) {
767
- return undefined;
768
- }
769
- const detail =
770
- typeof value.detail === 'object' && value.detail !== null
771
- ? { ...(value.detail as Record<string, unknown>) }
772
- : undefined;
773
- return {
774
- code: value.code,
775
- expected: value.expected,
776
- hint: value.hint,
777
- ...(detail === undefined ? {} : { detail }),
778
- };
779
- }
780
-
781
- /**
782
- * Project the producer-owned material and GPU store state into the one
783
- * renderer observation surface. This is intentionally recomputed from the
784
- * current frame's detached material snapshots; no readiness map is retained
785
- * by RenderSystem. A producer failure with an already resident resource is
786
- * reported as last-known-good, preserving recovery context without copying
787
- * the producer's lifecycle state.
788
- */
789
- function observeMaterialResidency(
790
- world: World | undefined,
791
- material: MaterialSnapshot,
792
- internals: RenderSystemInternals,
793
- ): MeshMaterialBindingResidency {
794
- const textures: Array<{ readonly handle: number; readonly mipLevelCount: number }> = [];
795
- const samplers: Array<{ readonly handle: number; readonly resident: boolean }> = [];
796
- let pending = false;
797
- let resident = false;
798
- let failure: MeshMaterialBindingPreparationFailure | undefined;
799
- const keepFailure = (error: unknown): void => {
800
- if (failure === undefined) failure = preparationFailureFrom(error);
801
- };
802
-
803
- if (world === undefined) {
804
- pending = true;
805
- } else {
806
- const materialHandle = material.materialHandle;
807
- if (materialHandle !== undefined && materialHandle !== 0) {
808
- const materialResult = resolveAssetHandle<MaterialAsset>(
809
- world,
810
- toShared<'MaterialAsset'>(materialHandle),
811
- );
812
- if (!materialResult.ok) {
813
- keepFailure(materialResult.error);
814
- } else {
815
- const guid = internals.assets.guidOf(materialResult.value);
816
- if (guid !== undefined) {
817
- const readiness = internals.assets.getMaterialReadiness(guid);
818
- if (readiness?.status === 'Error') keepFailure(readiness.error);
819
- const load = internals.assets.loadState.get(guid);
820
- if (load?.status === 'provisional') pending = true;
821
- }
822
- }
823
- }
824
-
825
- for (const handle of materialTextureHandles(material)) {
826
- const existing = internals.gpuStore.getTextureGpuView(handle, world);
827
- const pod = resolveAssetHandle<TextureAsset>(world, handle);
828
- if (!pod.ok) {
829
- keepFailure(pod.error);
830
- continue;
831
- }
832
- let view = existing;
833
- if (view === undefined) {
834
- const prepared = internals.gpuStore.ensureResident(handle, pod.value, world);
835
- if (!prepared.ok) keepFailure(prepared.error);
836
- view = internals.gpuStore.getTextureGpuView(handle, world);
837
- }
838
- if (view === undefined) {
839
- pending = failure === undefined;
840
- continue;
841
- }
842
- const textureLayout = deriveTextureLayout({
843
- shape: pod.value.shape,
844
- format: pod.value.format,
845
- mips: pod.value.mips,
846
- });
847
- if (!textureLayout.ok) {
848
- keepFailure(textureLayout.error);
849
- continue;
850
- }
851
- resident = true;
852
- textures.push({
853
- handle: Number(handle),
854
- mipLevelCount: Math.max(1, textureLayout.value.levels.length),
855
- });
856
- }
857
-
858
- for (const handle of materialSamplerHandles(material)) {
859
- const pod = resolveAssetHandle<SamplerAsset>(world, handle);
860
- if (!pod.ok) {
861
- keepFailure(pod.error);
862
- samplers.push({ handle: Number(handle), resident: false });
863
- continue;
864
- }
865
- const prepared = internals.gpuStore.ensureSamplerResident(handle, pod.value, world);
866
- if (!prepared.ok) {
867
- keepFailure(prepared.error);
868
- samplers.push({ handle: Number(handle), resident: false });
869
- } else {
870
- resident = true;
871
- samplers.push({ handle: Number(handle), resident: true });
872
- }
873
- }
874
- // Video views are supplied by the dynamic host store at record time. They
875
- // are not static TextureAsset residents, so this bounded projection stays
876
- // pending until a dynamic observation contract exists rather than guessing
877
- // from the VideoAsset GUID.
878
- if ((material.videoTextureFields?.size ?? 0) > 0) pending = true;
879
- }
880
-
881
- const readiness =
882
- failure === undefined
883
- ? pending
884
- ? 'pending'
885
- : 'ready'
886
- : resident
887
- ? 'last-known-good'
888
- : 'failed';
889
- return {
890
- readiness,
891
- samplers,
892
- textures,
893
- ...(failure === undefined ? {} : { preparationFailure: failure }),
894
- };
895
- }
896
-
897
600
  export function createRenderSystem(internals: RenderSystemInternals): RenderSystem {
898
601
  const phaseCatalogRegistration = internals.profiler?.registerPhaseCatalog(
899
602
  'render',
@@ -909,6 +612,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
909
612
  });
910
613
  let preparedFeatureSkylightResources: SkylightBindGroupResources | undefined;
911
614
  const dynamicGeometryFrames = createDynamicGeometryFrameBindings();
615
+ let surfaceDynamicInputFrame: SurfaceDynamicInputFrame | undefined;
912
616
  let latestCamera: CameraSnapshot | undefined;
913
617
  // Last public parameter failure; cleared only after a valid extraction.
914
618
  let lastMotionBlurInvalidParams: MotionBlurValidationError | undefined;
@@ -929,7 +633,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
929
633
  if (!installed.ok) internals.errorRegistry.fire(installed.error);
930
634
  };
931
635
  const pointsLinesOwner = new StandardPointsLinesOwner(internals);
932
- const instanceCollections = new InstanceCollectionStore();
636
+ const instanceCollections = new InstanceProjectionStore();
933
637
  const reflectionProbeOwner = new ReflectionProbeRecordOwner(internals);
934
638
  const ssrFormatReceipts = new WeakMap<
935
639
  RhiDevice,
@@ -957,7 +661,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
957
661
  const persistentRenderScene = new PersistentRenderScene({
958
662
  getDevice: () => internals.device,
959
663
  onGpuError: (error) => internals.errorRegistry.fire(error),
960
- onSharedRefMutation: (worldId, handle) => {
664
+ onRuntimeAssetChange: (worldId, handle) => {
961
665
  internals.gpuStore.invalidateMesh(handle, preparedWorlds[worldId] ?? worldId);
962
666
  },
963
667
  instanceCollections,
@@ -1105,6 +809,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
1105
809
  ),
1106
810
  } satisfies import('./pipeline-builder').PipelineBuilderShaderModuleFactory);
1107
811
  let gpuDrivenRecoveryCount = 0;
812
+ const surfaceSubmissionObservation = new SurfaceSubmissionObservationOwner(
813
+ () => internals.deviceScope.generation,
814
+ );
1108
815
  let gpuDrivenProduction = createGpuDrivenOwner(
1109
816
  internals.device,
1110
817
  gpuDrivenShaderFactory,
@@ -1176,6 +883,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
1176
883
  // raw (material-handle-based, cross-world collision semantically correct).
1177
884
  const frameState: RenderFrameState = {
1178
885
  frameNumber: 0,
886
+ surfaceSubmissionObservation: undefined,
1179
887
  reflectionFallbackDemand: false,
1180
888
  ssrRequested: false,
1181
889
  ssrSpatialAdmission: undefined,
@@ -1203,6 +911,13 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
1203
911
  depthOfFieldCandidateGraph: null,
1204
912
  depthOfFieldAccepted: undefined,
1205
913
  depthOfFieldLastSubmitFailed: false,
914
+ barrelDistortionPreviousGraph: null,
915
+ barrelDistortionPreviousGraphKey: null,
916
+ barrelDistortionPreviousPerFrameGraph: undefined,
917
+ barrelDistortionPreviousGraphGeneration: 0,
918
+ barrelDistortionPreviousCompiledGraphGeneration: 0,
919
+ barrelDistortionPreviousStandardLightingGraphSignature: '',
920
+ barrelDistortionCandidateGraph: null,
1206
921
  volumetricFogPreviousGraph: null,
1207
922
  volumetricFogPreviousGraphKey: null,
1208
923
  volumetricFogCandidateGraph: null,
@@ -1221,6 +936,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
1221
936
  currentFrameObservationSource: undefined,
1222
937
  reflectionFallbackObservationSource: undefined,
1223
938
  lastSuccessfulCameraAntialias: undefined,
939
+ lastSuccessfulBarrelDistortion: undefined,
940
+ barrelDistortionGraphResolution: 'accepted',
1224
941
  temporalGpuState: undefined,
1225
942
  autoExposureGpuResources: undefined,
1226
943
  pendingAutoExposureGpuResources: undefined,
@@ -1326,7 +1043,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
1326
1043
  // publish the same transient failure on every render tick. Keep one
1327
1044
  // renderer-owned cooldown per structured feature failure while retaining
1328
1045
  // the original error for the first and periodic reports.
1329
- const pendingFeatureErrorLastReportedFrame = new Map<string, number>();
1046
+ const pendingFeatureErrorLastReportedFrame = new Map<string, PendingRenderFeatureErrorReport>();
1330
1047
  const resolveSsrDependencies = (requested: boolean): SsrDependenciesInspection => {
1331
1048
  // Explicit SSR capability preparation belongs to initialization. Inspection
1332
1049
  // only projects receipts and never starts work or creates image history.
@@ -1532,7 +1249,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
1532
1249
  const invalidatePostProcessModule = (id: string): void => {
1533
1250
  const entry = lookupPostProcess(id);
1534
1251
  if (entry !== undefined) {
1535
- internals.invalidateShaderModule?.(postProcessShaderModuleLabel(id, entry.source));
1252
+ internals.invalidateShaderModule?.(postProcessShaderModuleLabel(entry.source));
1536
1253
  }
1537
1254
  };
1538
1255
  // feat-20260621 M-A2 / w8: expose the eager-created per-id params UBO through
@@ -1622,6 +1339,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
1622
1339
  if (!destroyed.ok) internals.errorRegistry.fire(destroyed.error);
1623
1340
  }
1624
1341
  };
1342
+ const disposeActivePostProcessResources = (): void => {
1343
+ const resources = { device: postProcessParamsDevice, paramsBuffers: postProcessParamsBuffers };
1344
+ postProcessParamsBuffers = new Map();
1345
+ disposePostProcessResources(resources);
1346
+ };
1625
1347
  const preparePostProcessParamsResources = (
1626
1348
  featureEntries: ReadonlyMap<string, PostProcessShaderEntry>,
1627
1349
  ): Result<PostProcessParamsCandidate, RhiError> => {
@@ -1901,6 +1623,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
1901
1623
  };
1902
1624
  let lastMeshMaterialBindings: readonly MeshMaterialBindingObservation[] = [];
1903
1625
  let lastMeshMaterialBindingRenderables: readonly RenderableSnapshot[] | undefined;
1626
+ let lastPresentation: FramePresentation = 'pending';
1904
1627
  const createPreparedResolverFactory =
1905
1628
  (
1906
1629
  runtime: RenderSystemInternals,
@@ -2064,6 +1787,17 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
2064
1787
  ) {
2065
1788
  return err(new Error('prepared scene-depth pipeline requires a scene target'));
2066
1789
  }
1790
+ // The typed graph composes fullscreen feature bindings from its
1791
+ // current graph views and post-process parameter snapshot at encode
1792
+ // time. Do not manufacture a fallback bind group here: during
1793
+ // registration/recovery its params buffer can still be absent, and
1794
+ // a two-entry fallback cannot satisfy a params-aware layout.
1795
+ if (
1796
+ preparedPipelineIds.has(pipeline as object) &&
1797
+ descriptor.values.fullscreen === true
1798
+ ) {
1799
+ return ok(undefined);
1800
+ }
2067
1801
  if (preparedGroup0Pipelines.has(pipeline as object)) {
2068
1802
  const layout =
2069
1803
  (materialShaderId === undefined
@@ -2201,10 +1935,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
2201
1935
  createPreparedResolverCaches,
2202
1936
  });
2203
1937
  return {
2204
- instances: instanceCollections,
1938
+ setSurfaceDynamicInput(frame: SurfaceDynamicInputFrame | undefined): void {
1939
+ surfaceDynamicInputFrame = frame;
1940
+ },
2205
1941
  initializeSsr: ensureSsrFormatProbe,
2206
1942
  get instanceCollectionsInspection(): readonly InstanceCollectionInspection[] {
2207
- return instanceCollections._inspections();
1943
+ return instanceCollections._inspections(frameState.frameNumber - 1);
2208
1944
  },
2209
1945
  releaseProfilerCatalog(): void {
2210
1946
  releaseProfilerCatalog?.();
@@ -2217,9 +1953,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
2217
1953
  return persistentRenderScene.bounds(world, entity);
2218
1954
  },
2219
1955
  get renderScene(): RenderSceneInspection {
1956
+ const submission = surfaceSubmissionObservation.inspect();
2220
1957
  return {
2221
1958
  ...persistentRenderScene.inspect(),
2222
1959
  gpuDriven: gpuDrivenProduction.inspect(),
1960
+ ...(submission === undefined ? {} : { submission }),
2223
1961
  };
2224
1962
  },
2225
1963
  get gpuDrivenInspection(): GpuDrivenProductionInspection {
@@ -2274,6 +2012,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
2274
2012
  get reflectionFallbackCompletion(): Promise<void> | undefined {
2275
2013
  return frameState.reflectionFallbackCompletion;
2276
2014
  },
2015
+ get presentation(): FramePresentation {
2016
+ return lastPresentation;
2017
+ },
2277
2018
  isCubeCapturePending(target: RenderTarget): boolean {
2278
2019
  return cubeCaptureScheduler.inspect(target).candidateGeneration !== undefined;
2279
2020
  },
@@ -2465,6 +2206,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
2465
2206
  const profileSession = internals.profiler?.activeSession();
2466
2207
  let ownsProfileFrame = false;
2467
2208
  let submitted = false;
2209
+ // A failed draw cannot publish a startup completion fact. Reset the
2210
+ // projection before extraction so a later receipt never reuses an old
2211
+ // scene's readiness.
2212
+ lastPresentation = 'pending';
2468
2213
  // A prior failed record/submit may have staged a temporal capture. A
2469
2214
  // capture belongs only to the draw call that created it; discard it
2470
2215
  // before this call can prepare or commit a new candidate.
@@ -2568,6 +2313,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
2568
2313
  environment,
2569
2314
  environmentReady,
2570
2315
  volumetricFog,
2316
+ cloudLayer,
2571
2317
  renderables,
2572
2318
  dispatch,
2573
2319
  shadowCasterEntityKeys: extractedShadowCasterEntityKeys,
@@ -2796,6 +2542,17 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
2796
2542
  );
2797
2543
  const submissionRenderables = visibilityProjection.renderables;
2798
2544
  const submissionDispatch = visibilityProjection.dispatch;
2545
+ const presentationProjection = projectFramePresentation({
2546
+ hasCamera: cameras.length > 0,
2547
+ environmentReady,
2548
+ hasEnvironment: environment !== undefined,
2549
+ submissionRenderables,
2550
+ submissionDispatch,
2551
+ preparedWorlds,
2552
+ internals,
2553
+ });
2554
+ const presentationRenderables = presentationProjection.renderables;
2555
+ let framePresentation = presentationProjection.presentation;
2799
2556
  const inspectionCamera = latestCamera;
2800
2557
  // The public frame receipt is allocated by WebGPURenderer immediately
2801
2558
  // before this draw (`observationFrameId`). RenderSystem's private
@@ -2991,6 +2748,17 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
2991
2748
  bindGroupCounts.createBindGroup = 0;
2992
2749
  bindGroupCounts.keys = [];
2993
2750
  const preparedPipelineState = internals.getPipelineState();
2751
+ const featureView = createCloudFeatureView(
2752
+ cameras[0],
2753
+ compositionWorlds,
2754
+ cameraOwner,
2755
+ internals.canvas.width,
2756
+ internals.canvas.height,
2757
+ internals.deviceScope.generation,
2758
+ frameState.lastSuccessfulTemporalView === undefined,
2759
+ lastSubmittedGeneration !== undefined &&
2760
+ lastSubmittedGeneration !== internals.deviceScope.generation,
2761
+ );
2994
2762
  const bindGroupSkipReason: RenderPhaseSkipReason | undefined =
2995
2763
  internals.featureHost === undefined
2996
2764
  ? 'feature-host-unavailable'
@@ -3041,6 +2809,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3041
2809
  colorAttachmentFormat: preparedPipelineState.colorAttachmentFormat,
3042
2810
  storageBuffer: internals.device.caps.storageBuffer,
3043
2811
  multisample: internals.device.caps.backendKind !== 'wgpu-webgl2',
2812
+ cloudHistory: cloudLayer !== undefined,
3044
2813
  });
3045
2814
  const motionBlurParams = cameras[0]?.motionBlur;
3046
2815
  let motionBlurDelta = 0;
@@ -3092,12 +2861,14 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3092
2861
  worlds: compositionWorlds,
3093
2862
  owner: resourceOwner,
3094
2863
  frameNumber: frameState.frameNumber,
2864
+ ...(cameras[0] === undefined ? {} : { selectedCamera: cameras[0] }),
3095
2865
  frameSize: { width: internals.canvas.width, height: internals.canvas.height },
3096
2866
  visibilitySnapshots: frame.featureVisibilitySnapshots,
3097
2867
  hiddenEntityReports: frame.hiddenEntityReports,
3098
2868
  targets: featureTargets,
3099
2869
  generation: internals.featureHost?.preparedGeneration ?? 0,
3100
2870
  caps: internals.device.caps,
2871
+ frame: createCloudFeatureFrameContext(cloudLayer, featureView),
3101
2872
  ...(internals.getMaterialShaderBindingContract === undefined
3102
2873
  ? {}
3103
2874
  : { materialShaderBindingContract: internals.getMaterialShaderBindingContract }),
@@ -3147,6 +2918,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3147
2918
  featureGraphCandidate = {
3148
2919
  plans: featureFrame.plans,
3149
2920
  fullscreenEffects: featureFrame.fullscreenEffects,
2921
+ postProcessIdentities: featureFrame.postProcessIdentities,
3150
2922
  ...(featureFrame.requiresPreparedResourceKey
3151
2923
  ? { preparedResourceKey: `frame-${frameState.frameNumber}` }
3152
2924
  : {}),
@@ -3288,11 +3060,44 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3288
3060
  Number.isFinite(deltaTime) ? Math.max(0, deltaTime) : 0,
3289
3061
  );
3290
3062
  }
3063
+ const surfaceSubmissionCandidate = surfaceSubmissionObservation.begin({
3064
+ frameId:
3065
+ (internals as RenderSystemInternals & { readonly observationFrameId?: number })
3066
+ .observationFrameId ?? frameState.frameNumber,
3067
+ requestedLane: opts.geometryLane === 'direct' ? 'direct' : 'gpu-driven',
3068
+ deviceGeneration: internals.deviceScope.generation,
3069
+ resourceGeneration: gpuDrivenProduction.inspect().resourceGeneration,
3070
+ });
3071
+ frameState.surfaceSubmissionObservation = surfaceSubmissionCandidate;
3291
3072
  const probeCaptureScene =
3292
3073
  shadowCasterProjection !== undefined &&
3293
3074
  reflectionProbeRecord.graph.work.some((work) => work.rawCaptureFace !== undefined)
3294
3075
  ? projectCaptureScene(shadowCasterProjection, submissionRenderables, orderedDispatch)
3295
3076
  : undefined;
3077
+ // This is a transient projection of the record owner's actual visible
3078
+ // draws. It lets the presentation fact distinguish a clear/submit
3079
+ // from a frame where geometry or its pipeline was skipped, without
3080
+ // retaining a second readiness registry or per-asset counter.
3081
+ const presentedRenderableKeys = new Set<number>();
3082
+ const presentedSubmeshKeys = new Set<string>();
3083
+ const consumeDynamicGeometry = dynamicGeometryFrames.onRenderableDraw(compositionWorlds);
3084
+ const markPresentedRenderable = (
3085
+ entry: Parameters<typeof consumeDynamicGeometry>[0],
3086
+ submeshIndex?: number,
3087
+ receipt?: RenderableDrawReceipt,
3088
+ ): void => {
3089
+ const entityKey = worldEntityKey(
3090
+ worldKeys[entry.source.worldId] ?? entry.source.worldId,
3091
+ entry.source.entityKey,
3092
+ );
3093
+ if (receipt?.ready !== false) {
3094
+ presentedRenderableKeys.add(entityKey);
3095
+ }
3096
+ if (submeshIndex !== undefined && receipt?.ready !== false) {
3097
+ presentedSubmeshKeys.add(`${entityKey}:${submeshIndex}`);
3098
+ }
3099
+ consumeDynamicGeometry(entry, receipt?.lane ?? 'cpu');
3100
+ };
3296
3101
  submitted = runProfiledRenderPhase(profileSession, 'record', () =>
3297
3102
  recordFrame(
3298
3103
  internals,
@@ -3325,6 +3130,15 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3325
3130
  deviceGeneration: internals.deviceScope.generation,
3326
3131
  },
3327
3132
  ...(occlusionProjection === undefined ? {} : { occlusion: occlusionProjection }),
3133
+ frameTime: (() => {
3134
+ const elapsed = (compositionWorlds[cameraOwner] as World).getResource(Time).elapsed;
3135
+ return Number.isFinite(elapsed) ? elapsed : 0;
3136
+ })(),
3137
+ deviceGeneration: internals.deviceScope.generation,
3138
+ ...(surfaceDynamicInputFrame === undefined
3139
+ ? {}
3140
+ : { surfaceDynamicInput: surfaceDynamicInputFrame }),
3141
+ ...(opts.geometryLane === undefined ? {} : { geometryLane: opts.geometryLane }),
3328
3142
  },
3329
3143
  compositionLeases,
3330
3144
  featureGraphCandidate,
@@ -3351,13 +3165,16 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3351
3165
  worldKeys,
3352
3166
  undefined,
3353
3167
  ssrDependencies,
3354
- dynamicGeometryFrames.onRenderableDraw(compositionWorlds),
3168
+ markPresentedRenderable,
3355
3169
  environment?.fog,
3356
3170
  opts.sampleTimeSeconds,
3357
3171
  opts.temporalReset === true,
3172
+ frame.cloudLayer,
3358
3173
  ),
3359
3174
  );
3360
3175
  dynamicGeometryFrames.commit(submitted);
3176
+ if (!submitted) surfaceSubmissionCandidate.abort();
3177
+ frameState.surfaceSubmissionObservation = undefined;
3361
3178
  if (!submitted) discardLiveFeatureState();
3362
3179
  if (submitted && lastLodOcclusionInspection !== undefined) {
3363
3180
  const query = ensureOcclusionRuntime().inspect();
@@ -3381,6 +3198,111 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3381
3198
  (frameState.currentDirectionalShadowView !== null &&
3382
3199
  (lights.lightViewProj?.length ?? 0) > 0 &&
3383
3200
  (internals.getPipelineState()?.perPassResources.shadowMapSize ?? 0) > 0);
3201
+
3202
+ // A successful queue submit is necessary but not sufficient for the
3203
+ // startup presentation fact. Reuse the same visible snapshots and
3204
+ // producer-owned GPU stores consumed by record so missing geometry,
3205
+ // material bindings, dynamic video frames, or requested shadow work
3206
+ // cannot dismiss the loading screen behind a clear/fallback pass.
3207
+ if (submitted && framePresentation === 'ready' && cameras.length > 0) {
3208
+ const pipelineState = internals.getPipelineState();
3209
+ const visibleRenderableKeys = new Set(
3210
+ presentationRenderables.map((renderable) =>
3211
+ worldEntityKey(
3212
+ worldKeys[renderable.worldId] ?? renderable.worldId,
3213
+ renderable.entityKey,
3214
+ ),
3215
+ ),
3216
+ );
3217
+ if (
3218
+ pipelineState === null ||
3219
+ frameState.compiledFrameGraph === null ||
3220
+ [...visibleRenderableKeys].some((key) => !presentedRenderableKeys.has(key))
3221
+ ) {
3222
+ framePresentation = 'pending';
3223
+ }
3224
+ for (const renderable of presentationRenderables) {
3225
+ if (framePresentation === 'pending') break;
3226
+ const renderableWorld = preparedWorlds[renderable.worldId];
3227
+ const meshHandles =
3228
+ renderableWorld === undefined
3229
+ ? undefined
3230
+ : (internals.gpuStore.getMeshGpuHandles(
3231
+ toShared<'MeshAsset'>(renderable.assetHandle),
3232
+ renderableWorld,
3233
+ ) ?? pipelineState?.meshes.get(renderable.assetHandle));
3234
+ if (meshHandles === undefined) {
3235
+ framePresentation = 'pending';
3236
+ break;
3237
+ }
3238
+ const entityKey = worldEntityKey(
3239
+ worldKeys[renderable.worldId] ?? renderable.worldId,
3240
+ renderable.entityKey,
3241
+ );
3242
+ const gpuClaimedSubmeshes = new Set<number>();
3243
+ for (const [compactIndex, draw] of (renderable.gpuDrivenDraws ?? []).entries()) {
3244
+ const submeshIndex = draw.drawItemIndex ?? compactIndex;
3245
+ if (presentedSubmeshKeys.has(`${entityKey}:${submeshIndex}`)) {
3246
+ gpuClaimedSubmeshes.add(submeshIndex);
3247
+ }
3248
+ }
3249
+ if (renderable.pointsLines === undefined) {
3250
+ for (const [submeshIndex] of meshHandles.submeshes.entries()) {
3251
+ if (gpuClaimedSubmeshes.has(submeshIndex)) continue;
3252
+ if (!presentedSubmeshKeys.has(`${entityKey}:${submeshIndex}`)) {
3253
+ framePresentation = 'pending';
3254
+ break;
3255
+ }
3256
+ }
3257
+ }
3258
+ if (framePresentation === 'pending') break;
3259
+ for (const material of renderable.materials) {
3260
+ const residency = observeMaterialResidency(renderableWorld, material, internals);
3261
+ if (residency.readiness === 'pending' || residency.readiness === 'failed') {
3262
+ framePresentation = 'pending';
3263
+ break;
3264
+ }
3265
+ for (const clip of material.videoTextureFields?.values() ?? []) {
3266
+ if (internals.dynamicTextureStore?.getView(clip) === undefined) {
3267
+ framePresentation = 'pending';
3268
+ break;
3269
+ }
3270
+ }
3271
+ if (framePresentation === 'pending') break;
3272
+ }
3273
+ if (framePresentation === 'pending') break;
3274
+ }
3275
+ if (
3276
+ framePresentation === 'ready' &&
3277
+ directionalQuality !== undefined &&
3278
+ (!directionalShadowReady ||
3279
+ (shadowCasterDrawKeys.size > 0 &&
3280
+ !frameState.directionalShadowCacheRecorded &&
3281
+ frameState.directionalShadowCache === null))
3282
+ ) {
3283
+ framePresentation = 'pending';
3284
+ }
3285
+ if (
3286
+ framePresentation === 'ready' &&
3287
+ lights.pointShadow.some(
3288
+ (shadow) =>
3289
+ shadow.shadowAtlasLayer >= 0 &&
3290
+ (shadow.shadowMatrices.length < 96 ||
3291
+ [...shadow.shadowMatrices].some((value) => !Number.isFinite(value))),
3292
+ )
3293
+ ) {
3294
+ framePresentation = 'pending';
3295
+ }
3296
+ if (
3297
+ framePresentation === 'ready' &&
3298
+ lights.spot.some(
3299
+ (spot) =>
3300
+ spot.castShadow && (spot.lightViewProj === undefined || spot.shadowAtlasTile < 0),
3301
+ )
3302
+ ) {
3303
+ framePresentation = 'pending';
3304
+ }
3305
+ }
3384
3306
  if (submitted && directionalShadowReady) {
3385
3307
  lastDirectionalShadowCandidate = 'accepted';
3386
3308
  } else if (directionalQuality !== undefined) {
@@ -3398,6 +3320,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3398
3320
  };
3399
3321
  }
3400
3322
  if (submitted) {
3323
+ lastPresentation = framePresentation;
3401
3324
  recoveryOwner.setLastSuccessfulFrameSeed({
3402
3325
  frame,
3403
3326
  worlds: compositionWorlds,
@@ -3405,6 +3328,19 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3405
3328
  resourceOwner: composition.owners.resourceOwner,
3406
3329
  width: Math.max(1, internals.canvas.width),
3407
3330
  height: Math.max(1, internals.canvas.height),
3331
+ frameTime: (() => {
3332
+ const elapsed = (compositionWorlds[cameraOwner] as World).getResource(Time).elapsed;
3333
+ return Number.isFinite(elapsed) ? elapsed : 0;
3334
+ })(),
3335
+ ...(surfaceDynamicInputFrame === undefined
3336
+ ? {}
3337
+ : { surfaceDynamicInput: surfaceDynamicInputFrame }),
3338
+ ...(frameState.recoveryMaterialArtifacts === undefined
3339
+ ? {}
3340
+ : { materialArtifacts: frameState.recoveryMaterialArtifacts }),
3341
+ ...(frameState.recoveryShadowMaterialArtifacts === undefined
3342
+ ? {}
3343
+ : { shadowMaterialArtifacts: frameState.recoveryShadowMaterialArtifacts }),
3408
3344
  });
3409
3345
  submittedFrameCount += 1;
3410
3346
  lastSubmittedGeneration = internals.deviceScope?.generation;
@@ -3418,13 +3354,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3418
3354
  internals.errorRegistry.fire(temporalCommit.error);
3419
3355
  }
3420
3356
  frameState.lastSuccessfulCameraAntialias = cameras[0]?.antialias;
3421
- const submittedCamera = cameras[0];
3422
3357
  const submittedDepthOfField =
3423
- submittedCamera === undefined
3358
+ cameras[0] === undefined
3424
3359
  ? undefined
3425
3360
  : resolveDepthOfFieldFrameParams(
3426
- submittedCamera.depthOfField,
3427
- submittedCamera.depthOfFieldError,
3361
+ cameras[0].depthOfField,
3362
+ cameras[0].depthOfFieldError,
3428
3363
  frameState.depthOfFieldAccepted?.params,
3429
3364
  );
3430
3365
  const submittedDepthOfFieldGraph = frameState.compiledFrameGraph?.inspect();
@@ -3521,6 +3456,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3521
3456
  },
3522
3457
  isDynamicGeometryConsumed: (world, entity, meshHandle) =>
3523
3458
  dynamicGeometryFrames.isConsumed(world, entity, meshHandle),
3459
+ dynamicGeometryRecordStageLane: (world, entity, meshHandle) =>
3460
+ dynamicGeometryFrames.recordStageLane(world, entity, meshHandle),
3524
3461
  pipelineDispatchCounts: dispatchCounts,
3525
3462
  observeCurrentFrame(options: FrameObservationOptions) {
3526
3463
  const currentFrameId = frameState.frameNumber - 1;
@@ -3557,6 +3494,20 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3557
3494
  )
3558
3495
  return;
3559
3496
  applyLodSelectionTelemetry(selection, capturedInspection, capturedWorldAttachments);
3497
+ if (
3498
+ selection.surfaceReadback !== undefined &&
3499
+ selection.surfaceActualMemberIds !== undefined &&
3500
+ selection.surfaceIndirectParameters !== undefined
3501
+ ) {
3502
+ surfaceSubmissionObservation.publishGpuMembers(
3503
+ {
3504
+ recording: selection.surfaceReadback,
3505
+ memberIds: selection.surfaceActualMemberIds,
3506
+ indirectParameters: selection.surfaceIndirectParameters,
3507
+ },
3508
+ receipt ?? capturedInspection.submit,
3509
+ );
3510
+ }
3560
3511
  const published = lastLodOcclusionInspection;
3561
3512
  if (
3562
3513
  published !== undefined &&
@@ -3621,9 +3572,18 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3621
3572
  get lastSuccessfulCameraAntialias(): CameraSnapshot['antialias'] | undefined {
3622
3573
  return frameState.lastSuccessfulCameraAntialias;
3623
3574
  },
3575
+ get lastSuccessfulBarrelDistortion(): BarrelDistortionMapping | undefined {
3576
+ return frameState.lastSuccessfulBarrelDistortion;
3577
+ },
3578
+ get barrelDistortionInspection(): BarrelDistortionInspection {
3579
+ return inspectBarrelDistortionState(frameState, internals.deviceScope?.generation ?? 0);
3580
+ },
3624
3581
  get perFrameGraphInfo(): CompiledRenderGraphInfo | undefined {
3625
3582
  return frameState.compiledFrameGraph?.inspect();
3626
3583
  },
3584
+ get renderGraphGenerationAllocation() {
3585
+ return inspectRenderGraphGenerationAllocation(frameState);
3586
+ },
3627
3587
  get featureGraphInspection(): import('./inspection-types').RenderFeatureGraphInspection {
3628
3588
  return getRenderFeatureGraphInspection(internals);
3629
3589
  },
@@ -3650,7 +3610,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3650
3610
  });
3651
3611
  },
3652
3612
  get volumetricFog(): import('./volume/inspection').VolumetricFogInspection {
3653
- return frameState.volumetricFogInspection;
3613
+ const accepted = frameState.volumetricFogAccepted;
3614
+ return {
3615
+ ...frameState.volumetricFogInspection,
3616
+ ownerCount: accepted === undefined ? 0 : 1 + (accepted.additional?.length ?? 0),
3617
+ };
3654
3618
  },
3655
3619
  configureStandard(config: RenderPipelineAsset['config']): void {
3656
3620
  const profileConfig = internals.standardProfile;
@@ -3729,7 +3693,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3729
3693
  }
3730
3694
  builtinPostProcessEntries.set(id, entry);
3731
3695
  if (paramsBuffer !== undefined) postProcessParamsBuffers.set(id, paramsBuffer);
3732
- const moduleLabel = postProcessShaderModuleLabel(id, entry.source);
3696
+ const moduleLabel = postProcessShaderModuleLabel(entry.source);
3733
3697
  return () => {
3734
3698
  if (builtinPostProcessEntries.get(id) === entry) {
3735
3699
  builtinPostProcessEntries.delete(id);
@@ -3778,6 +3742,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3778
3742
  internals.getPipelineState()?.perPassResources.drainBloomResources?.();
3779
3743
  internals.clearPostProcessPipelineCache?.('forgeax.taa-resolve');
3780
3744
  invalidatePostProcessModule('forgeax.taa-resolve');
3745
+ // Post-process parameter UBOs are renderer-owned persistent resources,
3746
+ // rather than graph-owned transient state. Clear the active table before
3747
+ // the feature host is retired so the renderer remains the sole owner.
3748
+ disposeActivePostProcessResources();
3749
+ resetSsaoResources(internals);
3781
3750
  resetHdrpBuffers(internals);
3782
3751
  // Retire graph-owned resources and dispose instance-buffer caches.
3783
3752
  // Both calls are idempotent + tolerate per-handle errors silently;
@@ -3789,6 +3758,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3789
3758
  frameState.directionalShadowCacheRecorded = false;
3790
3759
  frameState.currentFrameObservationSource = undefined;
3791
3760
  frameState.lastSuccessfulCameraAntialias = undefined;
3761
+ frameState.lastSuccessfulBarrelDistortion = undefined;
3762
+ frameState.cloudHistoryActive = false;
3763
+ delete frameState.pendingCloudHistoryActive;
3792
3764
  frameState.currentDirectionalShadowView = null;
3793
3765
  frameState.currentSpotShadowView = null;
3794
3766
  if (frameState.pendingAutoExposureGpuResources !== undefined) {
@@ -3816,6 +3788,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3816
3788
  retireTemporalGpuState(retiring);
3817
3789
  }
3818
3790
  frameState.retiringTemporalGpuStates.clear();
3791
+ settleBarrelDistortionGraphCandidate(frameState, false);
3819
3792
  settleVolumetricFogGraphCandidate(frameState, false);
3820
3793
  for (const buffer of frameState.volumetricFogParamsBuffers) {
3821
3794
  if (buffer === null) continue;
@@ -3849,9 +3822,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3849
3822
  frameState.depthOfFieldCandidateGraph = null;
3850
3823
  frameState.depthOfFieldAccepted = undefined;
3851
3824
  frameState.depthOfFieldLastSubmitFailed = false;
3852
- if (compiled !== null) compiled.retire().catch(() => undefined);
3825
+ resetBarrelDistortionGraphState(frameState);
3826
+ if (compiled !== null) retireCompiledGraph(frameState, compiled);
3853
3827
  for (const retired of frameState.retiredCompiledFrameGraphs) {
3854
- retired.retire().catch(() => undefined);
3828
+ retireCompiledGraph(frameState, retired);
3855
3829
  }
3856
3830
  frameState.retiredCompiledFrameGraphs.clear();
3857
3831
  // feat-20260619 M4 (D-6): pass errorRegistry to disposeInstanceBuffers
@@ -3871,6 +3845,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3871
3845
  }
3872
3846
  frameState.probeBlendRecordBufferCapacity = 0;
3873
3847
  frameState.probeBlendBuffers.clear();
3848
+ delete frameState.probeBlendRecordProjection;
3874
3849
  if (frameState.morphBuffers !== undefined) {
3875
3850
  for (const entry of frameState.morphBuffers.values()) {
3876
3851
  if (!entry.buffer.isDestroyed) {
@@ -3909,6 +3884,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3909
3884
  // device. Drop the shared Standard Cluster bundle before the next
3910
3885
  // frame asks for a new generation; resetHdrpBuffers fences the bundle
3911
3886
  // using its own device/queue instead of the replacement runtime device.
3887
+ resetSsaoResources(internals);
3912
3888
  resetHdrpBuffers(internals);
3913
3889
  // Keep the persistent material demand observable across device loss.
3914
3890
  // The physical resource has already been fenced by markDeviceLost(); the
@@ -3949,9 +3925,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3949
3925
  // must be discarded, not merely marked for destruction: their opaque
3950
3926
  // handles cannot be used on the fresh device and the next draw must
3951
3927
  // lazily build a new graph from the preserved ECS / asset POD caches.
3928
+ settleBarrelDistortionGraphCandidate(frameState, false);
3952
3929
  settleVolumetricFogGraphCandidate(frameState, false);
3953
3930
  settleDepthOfFieldGraphCandidate(frameState, false);
3954
- frameState.compiledFrameGraph?.retire().catch(() => undefined);
3931
+ if (frameState.compiledFrameGraph !== null) {
3932
+ retireCompiledGraph(frameState, frameState.compiledFrameGraph);
3933
+ }
3955
3934
  frameState.compiledFrameGraph = null;
3956
3935
  frameState.compiledFrameGraphTopologyKey = null;
3957
3936
  frameState.volumetricFogPreviousGraph = null;
@@ -3963,6 +3942,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3963
3942
  frameState.depthOfFieldPreviousGraphGeneration = 0;
3964
3943
  frameState.depthOfFieldPreviousStandardLightingGraphSignature = '';
3965
3944
  frameState.depthOfFieldCandidateGraph = null;
3945
+ resetBarrelDistortionGraphState(frameState);
3966
3946
  frameState.volumetricFogAccepted = undefined;
3967
3947
  frameState.volumetricFogAcceptedContext = undefined;
3968
3948
  frameState.volumetricFogHistoryGraph = null;
@@ -3989,6 +3969,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
3989
3969
  frameState.directionalShadowCacheRecorded = false;
3990
3970
  frameState.currentFrameObservationSource = undefined;
3991
3971
  frameState.lastSuccessfulCameraAntialias = undefined;
3972
+ frameState.lastSuccessfulBarrelDistortion = undefined;
3973
+ frameState.cloudHistoryActive = false;
3974
+ delete frameState.pendingCloudHistoryActive;
3992
3975
  frameState.temporalFrameTransaction.reset('device-recovery');
3993
3976
  frameState.temporalFrame = undefined;
3994
3977
  frameState.temporalFrameInput = undefined;
@@ -4011,7 +3994,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
4011
3994
  frameState.retiringTemporalGpuStates.clear();
4012
3995
  frameState.hdrpClusterMembership = null;
4013
3996
  for (const retired of frameState.retiredCompiledFrameGraphs) {
4014
- retired.retire().catch(() => undefined);
3997
+ retireCompiledGraph(frameState, retired);
4015
3998
  }
4016
3999
  frameState.retiredCompiledFrameGraphs.clear();
4017
4000
  frameState.instanceBuffers.clear();
@@ -4020,6 +4003,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
4020
4003
  delete frameState.probeBlendRecordBuffer;
4021
4004
  frameState.probeBlendRecordBufferCapacity = 0;
4022
4005
  frameState.probeBlendBuffers.clear();
4006
+ delete frameState.probeBlendRecordProjection;
4023
4007
  frameState.morphBuffers?.clear();
4024
4008
  frameState.transientInstanceBuffers = [];
4025
4009
  frameState.pointShadowAtlas = null;