@forgeax/engine-render 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/README.md +1374 -142
  2. package/dist/assembly/analytic-fog-registration.d.ts +3 -0
  3. package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
  4. package/dist/assembly/backend-contract.d.ts +2 -0
  5. package/dist/assembly/backend-contract.d.ts.map +1 -1
  6. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  7. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  8. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  9. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  10. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  11. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  12. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  13. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  15. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  16. package/dist/assembly/factory.d.ts +1 -1
  17. package/dist/assembly/factory.d.ts.map +1 -1
  18. package/dist/assembly/fxaa-registration.d.ts +4 -0
  19. package/dist/assembly/fxaa-registration.d.ts.map +1 -0
  20. package/dist/assembly/host-contract.d.ts +3 -3
  21. package/dist/assembly/host-contract.d.ts.map +1 -1
  22. package/dist/assembly/lod-observation.d.ts +4 -0
  23. package/dist/assembly/lod-observation.d.ts.map +1 -0
  24. package/dist/assembly/material/assembly.d.ts.map +1 -1
  25. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  26. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  27. package/dist/assembly/material-shader-policy.d.ts +16 -2
  28. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  29. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  30. package/dist/assembly/motion-blur-registration.d.ts +3 -0
  31. package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
  32. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  33. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  34. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  35. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  36. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  37. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  38. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  39. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  40. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  41. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  42. package/dist/assembly/renderer-inspection.d.ts +11 -0
  43. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  44. package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
  45. package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  47. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  48. package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
  49. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -1
  50. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  51. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  52. package/dist/assembly/webgpu-ready.d.ts +2 -2
  53. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  54. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  55. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  56. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  57. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  58. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  59. package/dist/authoring.mjs +1 -1
  60. package/dist/barrel-distortion.d.ts +47 -0
  61. package/dist/barrel-distortion.d.ts.map +1 -0
  62. package/dist/bloom-admission.d.ts +13 -0
  63. package/dist/bloom-admission.d.ts.map +1 -0
  64. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  65. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  66. package/dist/{chunk-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
  67. package/dist/chunk-HEB564WF.mjs.map +1 -0
  68. package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
  69. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  70. package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
  71. package/dist/{chunk-S665NJNF.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  72. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  73. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  74. package/dist/{chunk-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
  75. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  76. package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
  77. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  78. package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
  79. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  80. package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
  81. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  82. package/dist/cloud/density.d.ts +55 -0
  83. package/dist/cloud/density.d.ts.map +1 -0
  84. package/dist/cloud/extract.d.ts +25 -0
  85. package/dist/cloud/extract.d.ts.map +1 -0
  86. package/dist/cloud/feature.d.ts +57 -0
  87. package/dist/cloud/feature.d.ts.map +1 -0
  88. package/dist/cloud/frame-context.d.ts +8 -0
  89. package/dist/cloud/frame-context.d.ts.map +1 -0
  90. package/dist/cloud/inspection.d.ts +59 -0
  91. package/dist/cloud/inspection.d.ts.map +1 -0
  92. package/dist/cloud/optics.d.ts +56 -0
  93. package/dist/cloud/optics.d.ts.map +1 -0
  94. package/dist/cloud/parameters.d.ts +73 -0
  95. package/dist/cloud/parameters.d.ts.map +1 -0
  96. package/dist/cloud/resources.d.ts +60 -0
  97. package/dist/cloud/resources.d.ts.map +1 -0
  98. package/dist/cloud/shadow.d.ts +42 -0
  99. package/dist/cloud/shadow.d.ts.map +1 -0
  100. package/dist/cloud/temporal.d.ts +74 -0
  101. package/dist/cloud/temporal.d.ts.map +1 -0
  102. package/dist/components/atmosphere.d.ts +2 -0
  103. package/dist/components/atmosphere.d.ts.map +1 -1
  104. package/dist/components/barrel-distortion.d.ts +13 -0
  105. package/dist/components/barrel-distortion.d.ts.map +1 -0
  106. package/dist/components/camera.d.ts +20 -4
  107. package/dist/components/camera.d.ts.map +1 -1
  108. package/dist/components/cloud-layer.d.ts +29 -0
  109. package/dist/components/cloud-layer.d.ts.map +1 -0
  110. package/dist/components/index.d.ts +2 -0
  111. package/dist/components/index.d.ts.map +1 -1
  112. package/dist/components/instances.d.ts +20 -6
  113. package/dist/components/instances.d.ts.map +1 -1
  114. package/dist/components/mesh-filter.d.ts +6 -5
  115. package/dist/components/mesh-filter.d.ts.map +1 -1
  116. package/dist/components/motion-blur.d.ts +1 -0
  117. package/dist/components/motion-blur.d.ts.map +1 -1
  118. package/dist/construct-renderer.d.ts +1 -1
  119. package/dist/construct-renderer.d.ts.map +1 -1
  120. package/dist/construct-renderer.mjs +9751 -3528
  121. package/dist/construct-renderer.mjs.map +1 -1
  122. package/dist/device/gpu-residency.d.ts +6 -0
  123. package/dist/device/gpu-residency.d.ts.map +1 -1
  124. package/dist/dynamic-geometry.d.ts +5 -1
  125. package/dist/dynamic-geometry.d.ts.map +1 -1
  126. package/dist/environment/analytic-fog.d.ts +6 -0
  127. package/dist/environment/analytic-fog.d.ts.map +1 -0
  128. package/dist/errors/cloud.d.ts +59 -0
  129. package/dist/errors/cloud.d.ts.map +1 -0
  130. package/dist/errors/render.d.ts +23 -5
  131. package/dist/errors/render.d.ts.map +1 -1
  132. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  133. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  134. package/dist/extract/camera.d.ts.map +1 -1
  135. package/dist/extract/contracts.d.ts +12 -1
  136. package/dist/extract/contracts.d.ts.map +1 -1
  137. package/dist/extract/environment.d.ts +2 -0
  138. package/dist/extract/environment.d.ts.map +1 -1
  139. package/dist/features/barrel-distortion.d.ts +29 -0
  140. package/dist/features/barrel-distortion.d.ts.map +1 -0
  141. package/dist/features/error-reporting.d.ts +17 -0
  142. package/dist/features/error-reporting.d.ts.map +1 -0
  143. package/dist/features/host.d.ts +15 -0
  144. package/dist/features/host.d.ts.map +1 -1
  145. package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
  146. package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
  147. package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
  148. package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
  149. package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
  150. package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
  151. package/dist/features/plan.d.ts +15 -4
  152. package/dist/features/plan.d.ts.map +1 -1
  153. package/dist/features/prepared-gpu-work.d.ts +9 -5
  154. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  155. package/dist/features/render-graph-compute.d.ts.map +1 -1
  156. package/dist/features/render-graph-contribution.d.ts +5 -0
  157. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  158. package/dist/features/render-graph-raster.d.ts +1 -0
  159. package/dist/features/render-graph-raster.d.ts.map +1 -1
  160. package/dist/features/targets.d.ts +2 -0
  161. package/dist/features/targets.d.ts.map +1 -1
  162. package/dist/features/types.d.ts +44 -0
  163. package/dist/features/types.d.ts.map +1 -1
  164. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  165. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  166. package/dist/gpu-dirty-ranges.d.ts +11 -0
  167. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  168. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  169. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  170. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  171. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  172. package/dist/gpu-driven/prepared-draw.d.ts +7 -0
  173. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  174. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  175. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  176. package/dist/gpu-driven/production-raster.d.ts +50 -4
  177. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  178. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  179. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  180. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  181. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  182. package/dist/gpu-driven/view-gpu.d.ts +35 -2
  183. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  184. package/dist/gpu-scene.d.ts +11 -1
  185. package/dist/gpu-scene.d.ts.map +1 -1
  186. package/dist/hdrp-buffers.d.ts +2 -2
  187. package/dist/hdrp-buffers.d.ts.map +1 -1
  188. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  189. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  190. package/dist/index.d.ts +31 -8
  191. package/dist/index.d.ts.map +1 -1
  192. package/dist/index.mjs +258 -8
  193. package/dist/index.mjs.map +1 -1
  194. package/dist/inspection-types.d.ts +178 -3
  195. package/dist/inspection-types.d.ts.map +1 -1
  196. package/dist/instance-buffer-cache.d.ts +4 -4
  197. package/dist/instance-buffer-cache.d.ts.map +1 -1
  198. package/dist/instances.d.ts +49 -94
  199. package/dist/instances.d.ts.map +1 -1
  200. package/dist/internal.mjs +7 -7
  201. package/dist/pbr-pipeline.d.ts +19 -1
  202. package/dist/pbr-pipeline.d.ts.map +1 -1
  203. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  204. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  205. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  206. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  207. package/dist/pipeline/standard-output/types.d.ts +4 -2
  208. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  209. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  210. package/dist/pipeline/standard-post.d.ts +28 -19
  211. package/dist/pipeline/standard-post.d.ts.map +1 -1
  212. package/dist/pipeline-builder.d.ts +1 -1
  213. package/dist/pipeline-builder.d.ts.map +1 -1
  214. package/dist/pipeline-spec.d.ts +2 -2
  215. package/dist/plugin.d.ts.map +1 -1
  216. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  217. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  218. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  219. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  220. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  221. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  222. package/dist/record/fold-buckets.d.ts +95 -0
  223. package/dist/record/fold-buckets.d.ts.map +1 -0
  224. package/dist/record/fold-instance-buffer.d.ts +6 -0
  225. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  226. package/dist/record/frame-lighting.d.ts +1 -0
  227. package/dist/record/frame-lighting.d.ts.map +1 -1
  228. package/dist/record/frame-snapshot.d.ts +40 -3
  229. package/dist/record/frame-snapshot.d.ts.map +1 -1
  230. package/dist/record/frame-targets.d.ts.map +1 -1
  231. package/dist/record/frame.d.ts +14 -62
  232. package/dist/record/frame.d.ts.map +1 -1
  233. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  234. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  235. package/dist/record/gpu-timing.d.ts +8 -0
  236. package/dist/record/gpu-timing.d.ts.map +1 -1
  237. package/dist/record/main-pass-geometry.d.ts +21 -5
  238. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  239. package/dist/record/main-pass-material.d.ts +7 -1
  240. package/dist/record/main-pass-material.d.ts.map +1 -1
  241. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  242. package/dist/record/main-pass.d.ts +13 -2
  243. package/dist/record/main-pass.d.ts.map +1 -1
  244. package/dist/record/mesh-ssbo.d.ts +6 -5
  245. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  246. package/dist/record/motion-blur-receipt.d.ts +11 -0
  247. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  248. package/dist/record/probe-blend-buffer.d.ts +16 -0
  249. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  250. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  251. package/dist/record/render-context.d.ts +34 -31
  252. package/dist/record/render-context.d.ts.map +1 -1
  253. package/dist/record/shadow-pass.d.ts +2 -0
  254. package/dist/record/shadow-pass.d.ts.map +1 -1
  255. package/dist/record/skybox-post-pass.d.ts +6 -4
  256. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  257. package/dist/record/typed-frame-graph.d.ts +22 -2
  258. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  259. package/dist/record/view-ubo.d.ts +11 -3
  260. package/dist/record/view-ubo.d.ts.map +1 -1
  261. package/dist/record/volume-params.d.ts +9 -0
  262. package/dist/record/volume-params.d.ts.map +1 -0
  263. package/dist/recovery/render-system-candidate.d.ts +10 -0
  264. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  265. package/dist/reflection/record-owner.d.ts.map +1 -1
  266. package/dist/render-contract.d.ts +66 -8
  267. package/dist/render-contract.d.ts.map +1 -1
  268. package/dist/render-graph-primitives.d.ts.map +1 -1
  269. package/dist/render-pipeline.d.ts +106 -3
  270. package/dist/render-pipeline.d.ts.map +1 -1
  271. package/dist/render-system-extract-tail.d.ts +3 -2
  272. package/dist/render-system-extract-tail.d.ts.map +1 -1
  273. package/dist/render-system-extract.d.ts +24 -10
  274. package/dist/render-system-extract.d.ts.map +1 -1
  275. package/dist/render-system-presentation.d.ts +23 -0
  276. package/dist/render-system-presentation.d.ts.map +1 -0
  277. package/dist/render-system-producer-roots.d.ts +10 -0
  278. package/dist/render-system-producer-roots.d.ts.map +1 -0
  279. package/dist/render-system-residency.d.ts +12 -0
  280. package/dist/render-system-residency.d.ts.map +1 -0
  281. package/dist/render-system.d.ts +26 -15
  282. package/dist/render-system.d.ts.map +1 -1
  283. package/dist/scene/probe-blend.d.ts +27 -0
  284. package/dist/scene/probe-blend.d.ts.map +1 -1
  285. package/dist/scene/render-scene.d.ts +14 -5
  286. package/dist/scene/render-scene.d.ts.map +1 -1
  287. package/dist/ssao-buffers.d.ts +9 -0
  288. package/dist/ssao-buffers.d.ts.map +1 -1
  289. package/dist/surface/dynamic-input.d.ts +133 -0
  290. package/dist/surface/dynamic-input.d.ts.map +1 -0
  291. package/dist/surface/gpu-driven.d.ts +41 -0
  292. package/dist/surface/gpu-driven.d.ts.map +1 -0
  293. package/dist/surface/submission-observation.d.ts +136 -0
  294. package/dist/surface/submission-observation.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  296. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  297. package/dist/temporal/frame.d.ts +7 -0
  298. package/dist/temporal/frame.d.ts.map +1 -1
  299. package/dist/temporal/gpu.d.ts +13 -1
  300. package/dist/temporal/gpu.d.ts.map +1 -1
  301. package/dist/temporal/index.mjs +5 -5
  302. package/dist/temporal/inspection.d.ts.map +1 -1
  303. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  304. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  305. package/dist/temporal/view.d.ts +6 -1
  306. package/dist/temporal/view.d.ts.map +1 -1
  307. package/dist/transmission/single-layer-medium.d.ts +89 -0
  308. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  309. package/dist/typed-render-graph-primitives.d.ts +24 -9
  310. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  311. package/dist/volume/component.d.ts +9 -5
  312. package/dist/volume/component.d.ts.map +1 -1
  313. package/dist/volume/extract.d.ts +1 -1
  314. package/dist/volume/extract.d.ts.map +1 -1
  315. package/dist/volume/inspection.d.ts +2 -0
  316. package/dist/volume/inspection.d.ts.map +1 -1
  317. package/dist/volume/passes.d.ts +4 -1
  318. package/dist/volume/passes.d.ts.map +1 -1
  319. package/dist/volume/resources.d.ts.map +1 -1
  320. package/dist/volume/temporal.d.ts +3 -1
  321. package/dist/volume/temporal.d.ts.map +1 -1
  322. package/package.json +22 -21
  323. package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
  324. package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
  325. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  326. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  327. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  328. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  329. package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
  330. package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
  331. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  332. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  333. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  334. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  335. package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
  336. package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
  337. package/src/__tests__/environment-selection.unit.test.ts +12 -0
  338. package/src/__tests__/factory-contract.integration.test.ts +626 -113
  339. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  340. package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
  341. package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +2 -1
  347. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  348. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  349. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  350. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +7 -6
  351. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
  352. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
  353. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  354. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  355. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  356. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  357. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  358. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  359. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  360. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
  361. package/src/__tests__/gpu-scene.unit.test.ts +210 -9
  362. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  363. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  364. package/src/__tests__/instances-store.unit.test.ts +105 -238
  365. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  366. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  367. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  368. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  369. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
  370. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  371. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  372. package/src/__tests__/motion-blur-compute.dawn.test.ts +589 -0
  373. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  374. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  375. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  376. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  377. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
  378. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  379. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
  380. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  381. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  382. package/src/__tests__/public-surface.test-d.ts +8 -0
  383. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  384. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  385. package/src/__tests__/render-error-code-owner.test-d.ts +9 -0
  386. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  387. package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
  388. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  389. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  390. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
  391. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  392. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  393. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +37 -6
  394. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  395. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  396. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  397. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  398. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  399. package/src/__tests__/renderer-frame-transaction.integration.test.ts +33 -11
  400. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  401. package/src/__tests__/shader-manifest-fixture.ts +4 -4
  402. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  403. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  404. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  405. package/src/__tests__/skinned-shadow-caster.test.ts +17 -0
  406. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  407. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  408. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  409. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  410. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  411. package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
  412. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  413. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  414. package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
  415. package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
  416. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  417. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  418. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  419. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  420. package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
  421. package/src/__tests__/temporal-view.unit.test.ts +2 -1
  422. package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
  423. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  424. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  425. package/src/__tests__/volume-optics-oracle.unit.test.ts +7 -3
  426. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
  427. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  428. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  429. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  430. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +558 -68
  431. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
  432. package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
  433. package/src/assembly/analytic-fog-registration.ts +14 -0
  434. package/src/assembly/backend-contract.ts +30 -0
  435. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  436. package/src/assembly/canvas-draw-guard.ts +11 -0
  437. package/src/assembly/cloud-shadow-entry.ts +22 -0
  438. package/src/assembly/dynamic-geometry-host.ts +65 -37
  439. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  440. package/src/assembly/factory.ts +2 -30
  441. package/src/assembly/fxaa-registration.ts +17 -0
  442. package/src/assembly/host-contract.ts +3 -3
  443. package/src/assembly/lod-observation.ts +12 -0
  444. package/src/assembly/material/assembly.ts +25 -13
  445. package/src/assembly/material/pipeline-helpers.ts +53 -12
  446. package/src/assembly/material-shader-policy.ts +55 -0
  447. package/src/assembly/material-shader-prewarm.ts +21 -10
  448. package/src/assembly/motion-blur-registration.ts +17 -0
  449. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  450. package/src/assembly/recovery/renderer-recover.ts +41 -18
  451. package/src/assembly/render-feature-post-processes.ts +54 -0
  452. package/src/assembly/renderer-facade.ts +6 -1
  453. package/src/assembly/renderer-feature-inspection.ts +8 -2
  454. package/src/assembly/renderer-frame-transaction.ts +23 -0
  455. package/src/assembly/renderer-inspection.ts +28 -0
  456. package/src/assembly/skin-palette-owner.ts +1 -1
  457. package/src/assembly/temporal-post-process-prewarm.ts +40 -0
  458. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  459. package/src/assembly/webgpu-ready-contract.ts +8 -3
  460. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  461. package/src/assembly/webgpu-ready.ts +296 -306
  462. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  463. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  464. package/src/assembly/webgpu-renderer.ts +228 -281
  465. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  466. package/src/barrel-distortion.ts +247 -0
  467. package/src/bloom-admission.ts +21 -0
  468. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  469. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  470. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  471. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  472. package/src/cloud/density.ts +600 -0
  473. package/src/cloud/extract.ts +110 -0
  474. package/src/cloud/feature.ts +1810 -0
  475. package/src/cloud/frame-context.ts +42 -0
  476. package/src/cloud/inspection.ts +130 -0
  477. package/src/cloud/optics.ts +285 -0
  478. package/src/cloud/parameters.ts +255 -0
  479. package/src/cloud/resources.ts +122 -0
  480. package/src/cloud/shadow.ts +167 -0
  481. package/src/cloud/temporal.ts +226 -0
  482. package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
  483. package/src/components/atmosphere.ts +4 -0
  484. package/src/components/barrel-distortion.ts +46 -0
  485. package/src/components/camera.ts +66 -10
  486. package/src/components/cloud-layer.ts +47 -0
  487. package/src/components/index.ts +2 -0
  488. package/src/components/instances.ts +18 -45
  489. package/src/components/mesh-filter.ts +11 -9
  490. package/src/components/motion-blur.ts +1 -0
  491. package/src/components/sprite-instances.ts +1 -1
  492. package/src/construct-renderer.ts +1 -1
  493. package/src/device/gpu-residency.ts +56 -12
  494. package/src/dynamic-geometry.ts +12 -1
  495. package/src/environment/analytic-fog.ts +44 -0
  496. package/src/environment/background.ts +2 -2
  497. package/src/errors/cloud.ts +103 -0
  498. package/src/errors/render.ts +58 -8
  499. package/src/examples/single-layer-medium-surface.ts +59 -0
  500. package/src/extract/camera.ts +35 -8
  501. package/src/extract/contracts.ts +12 -0
  502. package/src/extract/environment.ts +4 -0
  503. package/src/features/barrel-distortion.ts +172 -0
  504. package/src/features/error-reporting.ts +98 -0
  505. package/src/features/host.ts +138 -24
  506. package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
  507. package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
  508. package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
  509. package/src/features/motion-blur/motion-blur-params.ts +70 -2
  510. package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
  511. package/src/features/plan.ts +33 -8
  512. package/src/features/prepared-gpu-work.ts +86 -35
  513. package/src/features/render-graph-compute.ts +13 -5
  514. package/src/features/render-graph-contribution.ts +11 -0
  515. package/src/features/render-graph-raster.ts +45 -3
  516. package/src/features/targets.ts +66 -0
  517. package/src/features/types.ts +47 -0
  518. package/src/fullscreen-post-process-pass.ts +41 -9
  519. package/src/gpu-dirty-ranges.ts +48 -0
  520. package/src/gpu-driven/batch-topology.ts +53 -0
  521. package/src/gpu-driven/material-artifacts.ts +35 -32
  522. package/src/gpu-driven/prepared-draw.ts +27 -14
  523. package/src/gpu-driven/production-raster-material.ts +1894 -0
  524. package/src/gpu-driven/production-raster.ts +904 -787
  525. package/src/gpu-driven/resource-allocation.ts +142 -0
  526. package/src/gpu-driven/shadow-ownership.ts +71 -0
  527. package/src/gpu-driven/view-gpu.ts +181 -10
  528. package/src/gpu-scene.ts +259 -101
  529. package/src/hdrp-buffers.ts +4 -3
  530. package/src/ibl/skylight-bind-group.ts +49 -7
  531. package/src/index.ts +228 -9
  532. package/src/inspection-types.ts +222 -2
  533. package/src/instance-buffer-cache.ts +4 -4
  534. package/src/instances.ts +151 -492
  535. package/src/pbr-pipeline.ts +219 -13
  536. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  537. package/src/pipeline/standard-forward-lane.ts +313 -57
  538. package/src/pipeline/standard-output/graph.ts +8 -2
  539. package/src/pipeline/standard-output/types.ts +12 -1
  540. package/src/pipeline/standard-pipeline.ts +291 -18
  541. package/src/pipeline/standard-post.ts +397 -102
  542. package/src/pipeline-builder.ts +1 -1
  543. package/src/pipeline-spec.ts +5 -5
  544. package/src/plugin.ts +4 -0
  545. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  546. package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
  547. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  548. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  549. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  550. package/src/record/__tests__/temporal-payload.unit.test.ts +3 -2
  551. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  552. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  553. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  554. package/src/record/barrel-distortion-frame.ts +110 -0
  555. package/src/record/dynamic-geometry-consumption.ts +39 -9
  556. package/src/record/fold-buckets.ts +852 -0
  557. package/src/record/fold-instance-buffer.ts +51 -0
  558. package/src/record/frame-lighting.ts +36 -2
  559. package/src/record/frame-snapshot.ts +44 -4
  560. package/src/record/frame-targets.ts +10 -6
  561. package/src/record/frame.ts +373 -1099
  562. package/src/record/gpu-draw-receipts.ts +38 -0
  563. package/src/record/gpu-timing.ts +48 -5
  564. package/src/record/main-pass-geometry.ts +281 -83
  565. package/src/record/main-pass-material.ts +66 -4
  566. package/src/record/main-pass-sprite-draws.ts +13 -66
  567. package/src/record/main-pass.ts +156 -20
  568. package/src/record/mesh-ssbo.ts +43 -6
  569. package/src/record/motion-blur-receipt.ts +91 -0
  570. package/src/record/probe-blend-buffer.ts +180 -0
  571. package/src/record/recovery-pipeline.ts +35 -3
  572. package/src/record/render-context.ts +51 -31
  573. package/src/record/shadow-pass.ts +36 -2
  574. package/src/record/skybox-post-pass.ts +150 -200
  575. package/src/record/typed-frame-graph.ts +824 -44
  576. package/src/record/view-ubo.ts +26 -3
  577. package/src/record/volume-params.ts +225 -0
  578. package/src/recovery/render-system-candidate.ts +257 -52
  579. package/src/reflection/record-owner.ts +7 -3
  580. package/src/render-contract.ts +71 -8
  581. package/src/render-graph-primitives.ts +7 -1
  582. package/src/render-pipeline.ts +136 -1
  583. package/src/render-system-extract-tail.ts +72 -60
  584. package/src/render-system-extract.ts +117 -87
  585. package/src/render-system-presentation.ts +56 -0
  586. package/src/render-system-producer-roots.ts +96 -0
  587. package/src/render-system-residency.ts +159 -0
  588. package/src/render-system.ts +601 -482
  589. package/src/scene/probe-blend.ts +96 -4
  590. package/src/scene/render-scene.ts +431 -281
  591. package/src/ssao-buffers.ts +95 -2
  592. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  593. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  594. package/src/surface/dynamic-input.ts +658 -0
  595. package/src/surface/gpu-driven.ts +147 -0
  596. package/src/surface/submission-observation.ts +517 -0
  597. package/src/systems/skin-palette-allocator.ts +4 -1
  598. package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
  599. package/src/temporal/frame-coordinator.ts +8 -1
  600. package/src/temporal/frame.ts +20 -0
  601. package/src/temporal/gpu.ts +101 -17
  602. package/src/temporal/inspection.ts +7 -1
  603. package/src/temporal/standard-scene-data.ts +5 -0
  604. package/src/temporal/target-coverage-attachment.ts +4 -0
  605. package/src/temporal/view.ts +13 -2
  606. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  607. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  608. package/src/transmission/single-layer-medium.ts +322 -0
  609. package/src/typed-render-graph-primitives.ts +191 -50
  610. package/src/volume/component.ts +10 -10
  611. package/src/volume/extract.ts +11 -5
  612. package/src/volume/inspection.ts +3 -0
  613. package/src/volume/passes.ts +95 -8
  614. package/src/volume/resources.ts +2 -1
  615. package/src/volume/temporal.ts +11 -0
  616. package/dist/chunk-4NNZQCL3.mjs.map +0 -1
  617. package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
  618. package/dist/chunk-DRR7D3KX.mjs.map +0 -1
  619. package/dist/chunk-GWCEMDVR.mjs.map +0 -1
  620. package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
  621. package/dist/chunk-JRIPCMYC.mjs.map +0 -1
  622. package/dist/chunk-LULCA3OF.mjs +0 -1713
  623. package/dist/chunk-LULCA3OF.mjs.map +0 -1
  624. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
@@ -9,8 +9,11 @@ import {
9
9
  type Result,
10
10
  RhiError,
11
11
  } from '@forgeax/engine-rhi';
12
+ import type { MaterialShaderArtifact } from '@forgeax/engine-shader';
12
13
  import type { Handle, MeshAsset, SamplerAsset, TextureAsset } from '@forgeax/engine-types';
13
14
  import { toShared } from '@forgeax/engine-types';
15
+ import { standardBloomAdmitted } from '../bloom-admission';
16
+ import { cloudShadowResolutionForQuality } from '../cloud/parameters';
14
17
  import { createClusterBinScratch } from '../cluster-binner';
15
18
  import type { EnvironmentLifecycle } from '../environment/lifecycle';
16
19
  import {
@@ -19,6 +22,7 @@ import {
19
22
  type RenderFeaturePreparedGraphicsResolverInput,
20
23
  runRenderFeatureFrame,
21
24
  } from '../features/host';
25
+ import { motionBlurTemporalDemand } from '../features/motion-blur/motion-blur-params';
22
26
  import type { RenderFeatureGpuWorkOwner } from '../features/prepared-gpu-work';
23
27
  import { resolveStandardRenderFeatureTargets } from '../features/targets';
24
28
  import {
@@ -27,8 +31,12 @@ import {
27
31
  type PostProcessShaderEntry,
28
32
  postProcessShaderEntrySignature,
29
33
  } from '../fullscreen-post-process-pass';
30
- import { collectGpuDrivenMaterialArtifacts } from '../gpu-driven/material-artifacts';
34
+ import {
35
+ collectGpuDrivenMaterialArtifacts,
36
+ requiresProbeBlendRecord,
37
+ } from '../gpu-driven/material-artifacts';
31
38
  import { GpuDrivenProduction } from '../gpu-driven/production-raster';
39
+ import { disposeInstanceBufferChunks, disposeInstanceBuffers } from '../instance-buffer-cache';
32
40
  import { inspectStandardLighting } from '../pipeline/standard-lighting/inspection';
33
41
  import { retireAutoExposureGpuResources } from '../pipeline/standard-output/auto-exposure/gpu';
34
42
  import {
@@ -36,12 +44,15 @@ import {
36
44
  resetStandardOutputForDeviceLoss,
37
45
  } from '../pipeline/standard-output/resources';
38
46
  import type { PipelineBuilderShaderModuleFactory } from '../pipeline-builder';
47
+ import { standardTopologyVariantSet } from '../pipeline-spec';
39
48
  import { inspectPointShadow } from '../point-shadow-inspection';
40
49
  import type { PreparedGraphicsResolver } from '../prepare/prepared-graphics-resolver';
41
50
  import { gpuDrivenMeshesForFrame, validateRenderables } from '../record/frame';
42
51
  import { prepareFrameLighting } from '../record/frame-lighting';
43
52
  import type { RenderFrameState, ValidatedRenderable } from '../record/frame-snapshot';
53
+ import { resolveGeometryInstanceBuffer } from '../record/main-pass-geometry';
44
54
  import { computeSplitLdrSprite } from '../record/main-pass-sprite-draws';
55
+ import { ensureProbeBlendRecordBuffer } from '../record/probe-blend-buffer';
45
56
  import {
46
57
  prepareRecoveryPipelineReadiness,
47
58
  type RecoveryPipelineReadiness,
@@ -51,6 +62,8 @@ import {
51
62
  ensureCompiledFrameGraph,
52
63
  getRenderFeatureGraphState,
53
64
  type RenderFeatureGraphCandidate,
65
+ retire as retireCompiledGraph,
66
+ shareRenderGraphGenerationAllocationOwner,
54
67
  } from '../record/typed-frame-graph';
55
68
  import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID } from '../render-contract';
56
69
  import type {
@@ -60,6 +73,7 @@ import type {
60
73
  } from '../render-system-extract';
61
74
  import type { PersistentGpuDrivenCandidate, PersistentRenderScene } from '../scene/render-scene';
62
75
  import { SHADOW_ATLAS_DEFAULT_LAYERS } from '../shadow-atlas';
76
+ import { ReadonlyDynamicInputPage, type SurfaceDynamicInputFrame } from '../surface/dynamic-input';
63
77
  import { createTemporalFrameTransaction } from '../temporal/frame';
64
78
  import {
65
79
  getTemporalBindGroupResources,
@@ -91,6 +105,14 @@ export interface RecoveryFrameSeed {
91
105
  readonly resourceOwner: number;
92
106
  readonly width: number;
93
107
  readonly height: number;
108
+ /** Last submitted Surface page is reused while the replacement device warms. */
109
+ readonly surfaceDynamicInput?: SurfaceDynamicInputFrame;
110
+ /** Last submitted World/App time snapshot for the Surface frame ABI. */
111
+ readonly frameTime?: number;
112
+ /** Exact forward artifacts accepted by the submitted frame. */
113
+ readonly materialArtifacts?: ReadonlyMap<string, MaterialShaderArtifact>;
114
+ /** Exact ShadowCaster artifacts accepted by the submitted frame. */
115
+ readonly shadowMaterialArtifacts?: ReadonlyMap<string, MaterialShaderArtifact>;
94
116
  }
95
117
 
96
118
  export interface RenderSystemRecoveryDependencies {
@@ -211,9 +233,14 @@ export function createRenderSystemRecovery(
211
233
  let lastSuccessfulFrameSeed: RecoveryFrameSeed | undefined;
212
234
 
213
235
  const createRecoveryCandidateFrameState = (): RenderFrameState => {
214
- const { probeBlendRecordBuffer: discardedProbeBlendRecordBuffer, ...baseFrameState } =
215
- frameState;
236
+ const {
237
+ probeBlendRecordBuffer: discardedProbeBlendRecordBuffer,
238
+ instanceCollections: discardedInstanceInspection,
239
+ ...baseFrameState
240
+ } = frameState;
216
241
  void discardedProbeBlendRecordBuffer;
242
+ // Candidate uploads must not publish residency into the active inspection.
243
+ void discardedInstanceInspection;
217
244
  return {
218
245
  ...baseFrameState,
219
246
  successfulTemporalFrameIndex: 0,
@@ -254,15 +281,18 @@ export function createRenderSystemRecovery(
254
281
  retiredCompiledFrameGraphs: new Set(),
255
282
  currentFrameObservationSource: undefined,
256
283
  lastSuccessfulCameraAntialias: undefined,
284
+ lastSuccessfulBarrelDistortion: undefined,
257
285
  temporalGpuState: undefined,
258
286
  activeTemporalGpuState: undefined,
259
287
  retiringTemporalGpuStates: new Set(),
288
+ cloudHistoryActive: false,
260
289
  lastSuccessfulTemporalView: undefined,
261
290
  pendingTemporalCommit: { kind: 'none' },
262
291
  environmentGeneration: undefined,
263
292
  currentDirectionalShadowView: null,
264
293
  currentSpotShadowView: null,
265
294
  instanceBuffers: new Map(),
295
+ instanceBufferChunks: new Map(),
266
296
  morphBuffers: new Map(),
267
297
  hdrpClusterBinScratch: createClusterBinScratch(),
268
298
  hdrpClusterGridScratch: null,
@@ -297,6 +327,18 @@ export function createRenderSystemRecovery(
297
327
  candidate.recoveryReadiness.assertPreparedCache();
298
328
  }
299
329
  const previousFeatureHost = internals.featureHost;
330
+ // The candidate graph proves topology and pipeline readiness before the
331
+ // publication boundary, but its imported display view was acquired before
332
+ // the shared canvas context was reconfigured for the replacement device.
333
+ // Retire that frame-bound graph and preserve the prepared owners/caches;
334
+ // the first recovered frame recompiles the same topology against the
335
+ // newly configured context instead of submitting a view from the lost
336
+ // device generation.
337
+ const candidateDisplayGraph = candidate.frameState.compiledFrameGraph;
338
+ candidate.frameState.compiledFrameGraph = null;
339
+ candidate.frameState.compiledFrameGraphTopologyKey = null;
340
+ candidate.frameState.perFrameGraph = null;
341
+ candidateDisplayGraph?.retire().catch(() => undefined);
300
342
  // The caller enters this method only after the active generation swap and
301
343
  // after resetForRecover() has shed every lost-device owner. Replace the
302
344
  // whole device-bound frame projection so no stale cache/map/temporal view
@@ -368,6 +410,9 @@ export function createRenderSystemRecovery(
368
410
  if (camera === undefined) return { kind: 'no-seed' };
369
411
 
370
412
  const candidateFrameState = createRecoveryCandidateFrameState();
413
+ // Candidate graph generations are one renderer-owned allocation stream;
414
+ // publication changes their role, not their accounting owner.
415
+ shareRenderGraphGenerationAllocationOwner(frameState, candidateFrameState);
371
416
  resetStandardOutputForDeviceLoss(candidateFrameState, runtime.internals.deviceScope.generation);
372
417
  Object.assign(candidateFrameState, {
373
418
  temporalFrame: undefined,
@@ -380,6 +425,7 @@ export function createRenderSystemRecovery(
380
425
  let candidateFeatureHost: RenderFeatureHost | undefined;
381
426
  let candidateFeatureGpuWork: RenderFeatureGpuWorkOwner | undefined;
382
427
  let candidatePointsLines: RecoveryPointsLinesCandidate | undefined;
428
+ let candidateSurfacePage: ReadonlyDynamicInputPage | undefined;
383
429
  let candidateFeatureGraph: RenderFeatureGraphCandidate = {
384
430
  plans: Object.freeze([]),
385
431
  fullscreenEffects: new Map(),
@@ -404,7 +450,7 @@ export function createRenderSystemRecovery(
404
450
  candidateFrameState.compiledFrameGraph = null;
405
451
  candidateFrameState.perFrameGraph = null;
406
452
  try {
407
- graph?.retire().catch(() => undefined);
453
+ if (graph !== null) retireCompiledGraph(candidateFrameState, graph);
408
454
  } catch {
409
455
  // Candidate cleanup continues through every independent owner.
410
456
  }
@@ -428,10 +474,21 @@ export function createRenderSystemRecovery(
428
474
  candidateGpuDrivenScene = undefined;
429
475
  candidatePointsLines?.release();
430
476
  candidatePointsLines = undefined;
477
+ candidateSurfacePage?.release();
478
+ candidateSurfacePage = undefined;
479
+ disposeInstanceBuffers(candidateFrameState.instanceBuffers, runtime.internals.errorRegistry);
480
+ if (candidateFrameState.instanceBufferChunks !== undefined) {
481
+ disposeInstanceBufferChunks(
482
+ candidateFrameState.instanceBufferChunks,
483
+ runtime.internals.errorRegistry,
484
+ );
485
+ }
431
486
  candidateGpuStore.destroyAll();
432
487
  };
433
488
  const markPublished = (): void => {
434
489
  candidatePointsLines?.publish();
490
+ candidateSurfacePage?.release();
491
+ candidateSurfacePage = undefined;
435
492
  candidatePublished = true;
436
493
  };
437
494
  const failed = (
@@ -455,11 +512,101 @@ export function createRenderSystemRecovery(
455
512
  );
456
513
  if (!gpuScene.ok) return failed('candidate GPU scene preparation failed', gpuScene.error);
457
514
  candidateGpuDrivenScene = gpuScene.value;
515
+ candidateValidated = validateRenderables(
516
+ runtime.internals,
517
+ seed.worlds[seed.cameraOwner] as World,
518
+ seed.worlds,
519
+ runtime.pipelineState,
520
+ candidateFrameState,
521
+ seed.frame.renderables,
522
+ seed.frame.dispatch,
523
+ );
524
+ if (candidateValidated.length !== seed.frame.renderables.length) {
525
+ return failed('candidate validation did not retain every LKG-visible renderable');
526
+ }
527
+ const lighting = prepareFrameLighting(
528
+ runtime.internals,
529
+ candidateFrameState,
530
+ seed.frame.lights,
531
+ camera,
532
+ runtime.pipelineState,
533
+ );
534
+ if (!lighting.ok) return failed('candidate lighting preparation failed');
535
+ let recoverySurfaceDynamicInput = seed.surfaceDynamicInput;
536
+ if (
537
+ recoverySurfaceDynamicInput !== undefined &&
538
+ recoverySurfaceDynamicInput.page.deviceGeneration !==
539
+ runtime.internals.deviceScope.generation
540
+ ) {
541
+ const source = recoverySurfaceDynamicInput;
542
+ const created = ReadonlyDynamicInputPage.create({
543
+ sourceId: source.page.sourceId,
544
+ pageId: source.page.pageId,
545
+ schema: source.page.schema,
546
+ });
547
+ if (!created.ok) {
548
+ return failed('candidate Surface recovery page creation failed', created.error);
549
+ }
550
+ candidateSurfacePage = created.value;
551
+ // Preserve CPU-authored parameters before preparing the replacement GPU page.
552
+ candidateSurfacePage.bytes.set(source.page.bytes);
553
+ const reconfigured = candidateSurfacePage.reconfigureDevice(
554
+ runtime.internals.deviceScope.generation,
555
+ );
556
+ if (!reconfigured.ok) {
557
+ return failed('candidate Surface recovery page generation failed', reconfigured.error);
558
+ }
559
+ const ranges = (source.ranges ?? []).map((range) => {
560
+ const reserved = candidateSurfacePage?.reserveRange({
561
+ domain: range.domain,
562
+ recordStart: range.recordStart,
563
+ recordCount: range.recordCount,
564
+ instanceIndex: range.instanceIndex,
565
+ member: range.member,
566
+ });
567
+ if (reserved === undefined || !reserved.ok) {
568
+ throw reserved?.error ?? new Error('candidate Surface recovery range unavailable');
569
+ }
570
+ return reserved.value;
571
+ });
572
+ recoverySurfaceDynamicInput = {
573
+ page: candidateSurfacePage,
574
+ ranges,
575
+ projectionRevision: source.projectionRevision + 1,
576
+ frameTime: source.frameTime,
577
+ };
578
+ }
458
579
  if (candidateGpuDrivenScene.state !== undefined) {
459
580
  candidateGpuDrivenProduction = GpuDrivenProduction.forDevice(
460
581
  runtime.internals.device,
461
582
  gpuDrivenShaderFactory,
462
583
  );
584
+ const clustered = lighting.value.standard?.kind === 'clustered';
585
+ const standardVariantSet = standardTopologyVariantSet(
586
+ lighting.value.standard,
587
+ runtime.internals.device.caps.storageBuffer,
588
+ false,
589
+ );
590
+ const standardPbrArtifact = runtime.internals.getMaterialShaderArtifact?.(
591
+ 'forgeax::default-standard-pbr',
592
+ {
593
+ vertexColorAvailable: false,
594
+ deformation: 'rigid',
595
+ pass: 'forward',
596
+ address: 'scene-index',
597
+ variantSet: standardVariantSet,
598
+ },
599
+ );
600
+ const standardPbrSkinArtifact = runtime.internals.getMaterialShaderArtifact?.(
601
+ 'forgeax::pbr-skin',
602
+ {
603
+ vertexColorAvailable: false,
604
+ deformation: 'skin',
605
+ pass: 'forward',
606
+ address: 'scene-index',
607
+ variantSet: standardVariantSet,
608
+ },
609
+ );
463
610
  const shadowProjection = persistentRenderScene.shadowCasterProjection();
464
611
  // The retained scene owns prepared draw receipts. The extraction seed
465
612
  // precedes GPU admission and must not stand in for that projection.
@@ -480,20 +627,45 @@ export function createRenderSystemRecovery(
480
627
  },
481
628
  renderableIndex,
482
629
  }));
483
- const { materialArtifacts, shadowMaterialArtifacts, firstArtifact, firstSkinArtifact } =
484
- collectGpuDrivenMaterialArtifacts({
485
- rows: artifactRows(seed.frame.renderables),
486
- shadowRows: artifactRows(shadowProjection?.renderables ?? []),
487
- dispatch: seed.frame.dispatch,
488
- shadowDispatch: shadowProjection?.dispatch ?? seed.frame.dispatch,
489
- resolve: runtime.internals.getMaterialShaderArtifact,
490
- clustered:
491
- seed.frame.lights.point.length +
492
- seed.frame.lights.spot.length +
493
- seed.frame.lights.rect.length >
494
- 0 || candidateFrameState.installedPipelineConfig?.ssao?.enabled === true,
495
- reflectionFallback: candidateFrameState.reflectionFallbackDemand === true,
496
- });
630
+ const collectedArtifacts = collectGpuDrivenMaterialArtifacts({
631
+ rows: artifactRows(seed.frame.renderables),
632
+ shadowRows: artifactRows(shadowProjection?.renderables ?? []),
633
+ dispatch: seed.frame.dispatch,
634
+ shadowDispatch: shadowProjection?.dispatch ?? seed.frame.dispatch,
635
+ resolve: runtime.internals.getMaterialShaderArtifact,
636
+ clustered:
637
+ seed.frame.lights.point.length +
638
+ seed.frame.lights.spot.length +
639
+ seed.frame.lights.rect.length >
640
+ 0 || candidateFrameState.installedPipelineConfig?.ssao?.enabled === true,
641
+ reflectionFallback: candidateFrameState.reflectionFallbackDemand === true,
642
+ });
643
+ const materialArtifacts =
644
+ collectedArtifacts.materialArtifacts.size > 0
645
+ ? collectedArtifacts.materialArtifacts
646
+ : (seed.materialArtifacts ?? new Map());
647
+ const shadowMaterialArtifacts =
648
+ collectedArtifacts.shadowMaterialArtifacts.size > 0
649
+ ? collectedArtifacts.shadowMaterialArtifacts
650
+ : (seed.shadowMaterialArtifacts ?? new Map());
651
+ const firstMaterialArtifact = materialArtifacts.values().next().value as
652
+ | MaterialShaderArtifact
653
+ | undefined;
654
+ const firstSkinArtifact = [...materialArtifacts.values()].find(
655
+ (artifact) => artifact.receipt?.skinPaletteAddress !== undefined,
656
+ );
657
+ const firstArtifact = firstMaterialArtifact ?? standardPbrArtifact;
658
+ const materialSkinArtifact = firstSkinArtifact ?? standardPbrSkinArtifact;
659
+ const probeBlendRequested = [...materialArtifacts.values()].some((artifact) =>
660
+ requiresProbeBlendRecord(artifact),
661
+ );
662
+ const probeBlendRecordBuffer = probeBlendRequested
663
+ ? ensureProbeBlendRecordBuffer(
664
+ runtime.internals.device,
665
+ candidateFrameState,
666
+ candidateGpuDrivenScene.state.probeBlend,
667
+ )
668
+ : undefined;
497
669
  const prepared = candidateGpuDrivenProduction.prepare({
498
670
  scene: candidateGpuDrivenScene.state,
499
671
  camera,
@@ -505,11 +677,21 @@ export function createRenderSystemRecovery(
505
677
  ),
506
678
  viewBindGroupLayout: runtime.pipelineState.viewBindGroupLayout,
507
679
  meshResidencyEpoch: runtime.internals.gpuStore.meshResidencyEpoch,
508
-
680
+ hdrp:
681
+ clustered &&
682
+ ((lighting.value.standard?.prepared.local.length ?? 0) > 0 ||
683
+ candidateFrameState.installedPipelineConfig?.ssao?.enabled === true),
684
+ clustered,
509
685
  ...(firstArtifact === undefined ? {} : { materialArtifact: firstArtifact }),
510
- ...(firstSkinArtifact === undefined ? {} : { materialSkinArtifact: firstSkinArtifact }),
686
+ ...(materialSkinArtifact === undefined ? {} : { materialSkinArtifact }),
511
687
  ...(materialArtifacts.size === 0 ? {} : { materialArtifacts }),
512
688
  ...(shadowMaterialArtifacts.size === 0 ? {} : { shadowMaterialArtifacts }),
689
+ ...(probeBlendRecordBuffer === undefined ? {} : { probeBlendRecordBuffer }),
690
+ ...(seed.frameTime === undefined ? {} : { frameTime: seed.frameTime }),
691
+ ...(recoverySurfaceDynamicInput === undefined
692
+ ? {}
693
+ : { surfaceDynamicInput: recoverySurfaceDynamicInput }),
694
+ deviceGeneration: runtime.internals.deviceScope.generation,
513
695
  materialPipelineState: runtime.pipelineState,
514
696
  ...(runtime.internals.getMaterialShaderPipelineEntry === undefined
515
697
  ? {}
@@ -518,6 +700,25 @@ export function createRenderSystemRecovery(
518
700
  if (!prepared.ok) return failed('candidate GPU-driven preparation failed', prepared.error);
519
701
  preparedGpuDriven = prepared.value;
520
702
  }
703
+ // A fully GPU-owned frame recovers through GPU Scene above. Only mixed
704
+ // or direct frames need the legacy instance-buffer closure as well.
705
+ if (!preparedGpuDriven?.ownsAllDrawItems || !preparedGpuDriven.ownsAllShadowCasters) {
706
+ for (const entry of candidateValidated) {
707
+ if (entry.source.instances === undefined) continue;
708
+ const prepared = resolveGeometryInstanceBuffer(
709
+ {
710
+ runtime: runtime.internals,
711
+ pipelineState: runtime.pipelineState,
712
+ frameState: candidateFrameState,
713
+ bindGroupCounts: { createBindGroup: 0, keys: [] },
714
+ },
715
+ entry,
716
+ [],
717
+ false,
718
+ );
719
+ if (prepared === null) return failed('candidate instance preparation failed');
720
+ }
721
+ }
521
722
  candidateFeatureHost = runtime.internals.featureHost;
522
723
  if (candidateFeatureHost !== undefined && candidateFeatureHost.size > 0) {
523
724
  candidateFeatureGpuWork = createFeatureGpuWorkOwner(runtime.internals);
@@ -527,11 +728,17 @@ export function createRenderSystemRecovery(
527
728
  colorAttachmentFormat: runtime.pipelineState.colorAttachmentFormat,
528
729
  storageBuffer: runtime.internals.device.caps.storageBuffer,
529
730
  multisample: runtime.internals.device.caps.backendKind !== 'wgpu-webgl2',
731
+ cloudHistory: seed.frame.cloudLayer !== undefined,
530
732
  });
531
733
  const featureFrame = runRenderFeatureFrame(candidateFeatureHost, {
532
734
  worlds: seed.worlds,
533
735
  owner: seed.resourceOwner,
534
736
  frameNumber: candidateFrameState.frameNumber,
737
+ selectedCamera: camera,
738
+ frameSize: {
739
+ width: runtime.internals.canvas.width,
740
+ height: runtime.internals.canvas.height,
741
+ },
535
742
  visibilitySnapshots: seed.frame.featureVisibilitySnapshots,
536
743
  hiddenEntityReports: seed.frame.hiddenEntityReports,
537
744
  targets: featureTargets,
@@ -551,7 +758,7 @@ export function createRenderSystemRecovery(
551
758
  gpuWork: candidateFeatureGpuWork,
552
759
  });
553
760
  if (featureFrame.errors.length > 0) {
554
- return failed('candidate render-feature preparation failed');
761
+ return failed('candidate render-feature preparation failed', featureFrame.errors[0]);
555
762
  }
556
763
  const featurePreparationIncomplete = featureFrame.plans.some((planned) => {
557
764
  const execution = getRenderFeaturePlanExecutionProjection(planned);
@@ -580,6 +787,7 @@ export function createRenderSystemRecovery(
580
787
  candidateFeatureGraph = {
581
788
  plans: featureFrame.plans,
582
789
  fullscreenEffects: featureFrame.fullscreenEffects,
790
+ postProcessIdentities: featureFrame.postProcessIdentities,
583
791
  ...(batches.length === 0
584
792
  ? {}
585
793
  : { preparedResourceKey: `recovery-${runtime.internals.deviceScope.generation}` }),
@@ -672,26 +880,6 @@ export function createRenderSystemRecovery(
672
880
  }
673
881
  }
674
882
  }
675
- candidateValidated = validateRenderables(
676
- runtime.internals,
677
- resourceWorld,
678
- seed.worlds,
679
- runtime.pipelineState,
680
- candidateFrameState,
681
- seed.frame.renderables,
682
- seed.frame.dispatch,
683
- );
684
- if (candidateValidated.length !== seed.frame.renderables.length) {
685
- return failed('candidate validation did not retain every LKG-visible renderable');
686
- }
687
- const lighting = prepareFrameLighting(
688
- runtime.internals,
689
- candidateFrameState,
690
- seed.frame.lights,
691
- camera,
692
- runtime.pipelineState,
693
- );
694
- if (!lighting.ok) return failed('candidate lighting preparation failed');
695
883
  candidatePointsLines = pointsLinesOwner.prepareRecoveryCandidate(
696
884
  candidateValidated,
697
885
  lighting.value.standard?.kind === 'clustered',
@@ -717,7 +905,11 @@ export function createRenderSystemRecovery(
717
905
  });
718
906
  const candidatePostProcessIds = new Set<string>([
719
907
  ...(candidateFrameState.installedPipelineConfig?.postEffects ?? []),
720
- ...candidateFeatureGraph.fullscreenEffects.keys(),
908
+ // Required identities include effects disabled for this frame. Warm only
909
+ // published entries, using their public identity rather than graph aliases.
910
+ ...(candidateFeatureGraph.postProcessIdentities ?? []).filter((id) =>
911
+ candidateFeatureGraph.fullscreenEffects.has(id),
912
+ ),
721
913
  ]);
722
914
  const configuredPostEffects = candidateFrameState.installedPipelineConfig?.postEffects ?? [];
723
915
  const postProcessPipeline = runtime.internals.getPostProcessPipeline;
@@ -794,29 +986,35 @@ export function createRenderSystemRecovery(
794
986
  throw new Error('recovery TAA pipeline is unavailable');
795
987
  }
796
988
  }
797
- if (camera.motionBlur?.shutterAngle !== undefined && camera.motionBlur.shutterAngle > 0) {
989
+ if (
990
+ camera.motionBlur !== undefined &&
991
+ motionBlurTemporalDemand({
992
+ shutterAngle: camera.motionBlur.shutterAngle,
993
+ maxRadiusPixels: camera.motionBlur.maxRadiusPixels,
994
+ sampleCount: camera.motionBlur.sampleCount,
995
+ targetFps: camera.motionBlur.targetFps ?? 60,
996
+ })
997
+ ) {
798
998
  warmPostProcessPipeline('forgeax.motion-blur', 'rgba16float');
799
999
  }
800
1000
  for (const id of candidatePostProcessIds) {
801
1001
  warmPostProcessPipeline(id, runtime.pipelineState.format as GPUTextureFormat);
802
1002
  }
803
- if (camera.bloom === 'on' && camera.tonemap !== 'none') {
1003
+ if (standardBloomAdmitted(camera)) {
804
1004
  runtime.pipelineState.perPassResources.ensureBloomResources?.();
805
1005
  const bloom = runtime.pipelineState.perPassResources.getBloomResources?.();
806
1006
  if (
807
1007
  bloom === null ||
808
1008
  bloom === undefined ||
809
- bloom.bloomBrightPipeline === null ||
810
- bloom.bloomBlurHPipeline === null ||
811
- bloom.bloomBlurVPipeline === null ||
1009
+ bloom.bloomDownsamplePipeline === null ||
1010
+ bloom.bloomUpsamplePipeline === null ||
812
1011
  bloom.bloomCompositePipeline === null ||
813
- bloom.bloomBrightBindGroupLayout === null ||
814
- bloom.bloomBlurBindGroupLayout === null ||
1012
+ bloom.bloomDownsampleBindGroupLayout === null ||
1013
+ bloom.bloomUpsampleBindGroupLayout === null ||
815
1014
  bloom.bloomCompositeBindGroupLayout === null ||
816
1015
  bloom.bloomSampler === null ||
817
- bloom.bloomBrightParamsBuffer === null ||
818
- bloom.bloomBlurHParamsBuffer === null ||
819
- bloom.bloomBlurVParamsBuffer === null ||
1016
+ bloom.bloomDownsampleParamsBuffer === null ||
1017
+ bloom.bloomUpsampleParamsBuffer === null ||
820
1018
  bloom.bloomCompositeParamsBuffer === null
821
1019
  ) {
822
1020
  throw new Error('recovery Bloom resources are incomplete');
@@ -843,6 +1041,13 @@ export function createRenderSystemRecovery(
843
1041
  (error) => {
844
1042
  recoveryGraphFailure ??= error;
845
1043
  },
1044
+ undefined,
1045
+ undefined,
1046
+ false,
1047
+ false,
1048
+ seed.frame.cloudLayer === undefined
1049
+ ? undefined
1050
+ : cloudShadowResolutionForQuality(seed.frame.cloudLayer.params.quality),
846
1051
  );
847
1052
  if (graph === null) return failed('candidate frame graph compilation failed');
848
1053
  if (recoveryReadiness === undefined)
@@ -397,9 +397,13 @@ export class ReflectionProbeRecordOwner {
397
397
  this.lastFactCount = facts.length;
398
398
  this.lastScheduledRawFaces = 0;
399
399
  this.lastScheduledFilteredSteps = 0;
400
- const firstSelection = selections.values().next().value as
401
- | ReflectionProbeSelectionResult
402
- | undefined;
400
+ // The fallback MRT has one representative readback, so choose a stable
401
+ // non-neutral probe consumer when the scene contains one. Renderable map
402
+ // order is not a source-selection contract: the first entry is commonly
403
+ // an outside panel while the local probe consumer appears later.
404
+ const firstSelection =
405
+ [...selections.values()].find((selection) => selection.kind === 'probe') ??
406
+ (selections.values().next().value as ReflectionProbeSelectionResult | undefined);
403
407
  this.lastSelection =
404
408
  firstSelection?.kind === 'probe'
405
409
  ? {