@forgeax/engine-render 0.1.33 → 0.1.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/README.md +1062 -127
  2. package/dist/assembly/backend-contract.d.ts +2 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  5. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  6. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  7. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  8. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  9. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  10. package/dist/assembly/device-feature-admission.d.ts +2 -2
  11. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  12. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  15. package/dist/assembly/factory.d.ts +1 -1
  16. package/dist/assembly/factory.d.ts.map +1 -1
  17. package/dist/assembly/host-contract.d.ts +6 -5
  18. package/dist/assembly/host-contract.d.ts.map +1 -1
  19. package/dist/assembly/material/assembly.d.ts.map +1 -1
  20. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  21. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  22. package/dist/assembly/material-shader-policy.d.ts +16 -2
  23. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  24. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  26. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  27. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  28. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  29. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  30. package/dist/assembly/render-target-host.d.ts +5 -0
  31. package/dist/assembly/render-target-host.d.ts.map +1 -1
  32. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  33. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  34. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  35. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  36. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  37. package/dist/assembly/renderer-inspection.d.ts +11 -0
  38. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  41. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  42. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +1 -1
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  46. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  47. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  48. package/dist/assembly/webgpu-renderer.d.ts +2 -1
  49. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  50. package/dist/authoring.mjs +2 -4
  51. package/dist/authoring.mjs.map +1 -1
  52. package/dist/barrel-distortion.d.ts +47 -0
  53. package/dist/barrel-distortion.d.ts.map +1 -0
  54. package/dist/chunk-3XUBWRY2.mjs +1842 -0
  55. package/dist/chunk-3XUBWRY2.mjs.map +1 -0
  56. package/dist/{chunk-OO3DRYK7.mjs → chunk-G6HDNGY7.mjs} +2400 -1767
  57. package/dist/chunk-G6HDNGY7.mjs.map +1 -0
  58. package/dist/{chunk-ZDQWGQW7.mjs → chunk-LM5IE7GF.mjs} +4 -4
  59. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
  60. package/dist/{chunk-VOZWDM3L.mjs → chunk-LNIUIKQ7.mjs} +1514 -498
  61. package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
  62. package/dist/chunk-MXTWKZO4.mjs +3268 -0
  63. package/dist/chunk-MXTWKZO4.mjs.map +1 -0
  64. package/dist/chunk-MZ4C7EHF.mjs +6942 -0
  65. package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
  66. package/dist/chunk-RIPAEGI6.mjs +48 -0
  67. package/dist/chunk-RIPAEGI6.mjs.map +1 -0
  68. package/dist/{chunk-LEAXOMYJ.mjs → chunk-SGPUJW3F.mjs} +117 -5
  69. package/dist/chunk-SGPUJW3F.mjs.map +1 -0
  70. package/dist/{chunk-PA5DRJNI.mjs → chunk-X2KA6WHM.mjs} +29 -4
  71. package/dist/chunk-X2KA6WHM.mjs.map +1 -0
  72. package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
  73. package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
  74. package/dist/cloud/density.d.ts +55 -0
  75. package/dist/cloud/density.d.ts.map +1 -0
  76. package/dist/cloud/extract.d.ts +25 -0
  77. package/dist/cloud/extract.d.ts.map +1 -0
  78. package/dist/cloud/feature.d.ts +57 -0
  79. package/dist/cloud/feature.d.ts.map +1 -0
  80. package/dist/cloud/frame-context.d.ts +8 -0
  81. package/dist/cloud/frame-context.d.ts.map +1 -0
  82. package/dist/cloud/inspection.d.ts +59 -0
  83. package/dist/cloud/inspection.d.ts.map +1 -0
  84. package/dist/cloud/optics.d.ts +56 -0
  85. package/dist/cloud/optics.d.ts.map +1 -0
  86. package/dist/cloud/parameters.d.ts +73 -0
  87. package/dist/cloud/parameters.d.ts.map +1 -0
  88. package/dist/cloud/resources.d.ts +60 -0
  89. package/dist/cloud/resources.d.ts.map +1 -0
  90. package/dist/cloud/shadow.d.ts +42 -0
  91. package/dist/cloud/shadow.d.ts.map +1 -0
  92. package/dist/cloud/temporal.d.ts +74 -0
  93. package/dist/cloud/temporal.d.ts.map +1 -0
  94. package/dist/components/barrel-distortion.d.ts +13 -0
  95. package/dist/components/barrel-distortion.d.ts.map +1 -0
  96. package/dist/components/cloud-layer.d.ts +29 -0
  97. package/dist/components/cloud-layer.d.ts.map +1 -0
  98. package/dist/components/index.d.ts +2 -0
  99. package/dist/components/index.d.ts.map +1 -1
  100. package/dist/components/instances.d.ts +20 -6
  101. package/dist/components/instances.d.ts.map +1 -1
  102. package/dist/construct-renderer.d.ts +1 -1
  103. package/dist/construct-renderer.d.ts.map +1 -1
  104. package/dist/construct-renderer.mjs +8406 -5785
  105. package/dist/construct-renderer.mjs.map +1 -1
  106. package/dist/device/gpu-residency.d.ts +19 -19
  107. package/dist/device/gpu-residency.d.ts.map +1 -1
  108. package/dist/dynamic-geometry.d.ts +5 -1
  109. package/dist/dynamic-geometry.d.ts.map +1 -1
  110. package/dist/errors/cloud.d.ts +59 -0
  111. package/dist/errors/cloud.d.ts.map +1 -0
  112. package/dist/errors/render.d.ts +20 -5
  113. package/dist/errors/render.d.ts.map +1 -1
  114. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  115. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  116. package/dist/extract/camera.d.ts.map +1 -1
  117. package/dist/extract/contracts.d.ts +5 -1
  118. package/dist/extract/contracts.d.ts.map +1 -1
  119. package/dist/extract/material-context.d.ts +7 -0
  120. package/dist/extract/material-context.d.ts.map +1 -0
  121. package/dist/features/barrel-distortion.d.ts +29 -0
  122. package/dist/features/barrel-distortion.d.ts.map +1 -0
  123. package/dist/features/error-reporting.d.ts +6 -2
  124. package/dist/features/error-reporting.d.ts.map +1 -1
  125. package/dist/features/host.d.ts +15 -0
  126. package/dist/features/host.d.ts.map +1 -1
  127. package/dist/features/plan.d.ts +10 -0
  128. package/dist/features/plan.d.ts.map +1 -1
  129. package/dist/features/render-graph-contribution.d.ts +5 -0
  130. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  131. package/dist/features/render-graph-raster.d.ts +1 -0
  132. package/dist/features/render-graph-raster.d.ts.map +1 -1
  133. package/dist/features/targets.d.ts +2 -0
  134. package/dist/features/targets.d.ts.map +1 -1
  135. package/dist/features/types.d.ts +48 -0
  136. package/dist/features/types.d.ts.map +1 -1
  137. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  138. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  139. package/dist/glyph-text-layout-system.d.ts +1 -1
  140. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  141. package/dist/gpu-dirty-ranges.d.ts +11 -0
  142. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  143. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  144. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  145. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  146. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  147. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  148. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  149. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  150. package/dist/gpu-driven/production-raster.d.ts +47 -3
  151. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  152. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  153. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  154. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  155. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  156. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  157. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  158. package/dist/gpu-scene.d.ts +5 -0
  159. package/dist/gpu-scene.d.ts.map +1 -1
  160. package/dist/hdrp-buffers.d.ts +2 -2
  161. package/dist/hdrp-buffers.d.ts.map +1 -1
  162. package/dist/ibl/frame-resources.d.ts.map +1 -1
  163. package/dist/ibl/skylight-bind-group.d.ts +14 -5
  164. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  165. package/dist/index.d.ts +30 -7
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.mjs +780 -9
  168. package/dist/index.mjs.map +1 -1
  169. package/dist/inspection-types.d.ts +135 -1
  170. package/dist/inspection-types.d.ts.map +1 -1
  171. package/dist/instance-buffer-cache.d.ts +4 -4
  172. package/dist/instance-buffer-cache.d.ts.map +1 -1
  173. package/dist/instances.d.ts +47 -100
  174. package/dist/instances.d.ts.map +1 -1
  175. package/dist/internal.mjs +7 -8
  176. package/dist/internal.mjs.map +1 -1
  177. package/dist/pbr-pipeline.d.ts +22 -4
  178. package/dist/pbr-pipeline.d.ts.map +1 -1
  179. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  180. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  181. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  182. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  183. package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
  184. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
  185. package/dist/pipeline/standard-output/resources.d.ts +2 -2
  186. package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
  187. package/dist/pipeline/standard-output/types.d.ts +4 -2
  188. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  189. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  190. package/dist/pipeline/standard-post.d.ts.map +1 -1
  191. package/dist/pipeline-builder.d.ts +1 -1
  192. package/dist/pipeline-builder.d.ts.map +1 -1
  193. package/dist/plugin.d.ts.map +1 -1
  194. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  195. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  196. package/dist/publication/contract.d.ts +77 -0
  197. package/dist/publication/contract.d.ts.map +1 -0
  198. package/dist/publication/dependencies.d.ts +7 -0
  199. package/dist/publication/dependencies.d.ts.map +1 -0
  200. package/dist/publication/prepare-geometry.d.ts +9 -0
  201. package/dist/publication/prepare-geometry.d.ts.map +1 -0
  202. package/dist/publication/programs.d.ts +5 -0
  203. package/dist/publication/programs.d.ts.map +1 -0
  204. package/dist/publication/publisher.d.ts +33 -0
  205. package/dist/publication/publisher.d.ts.map +1 -0
  206. package/dist/publication/receiver.d.ts +29 -0
  207. package/dist/publication/receiver.d.ts.map +1 -0
  208. package/dist/publication/resource-scope.d.ts +18 -0
  209. package/dist/publication/resource-scope.d.ts.map +1 -0
  210. package/dist/publication/targets.d.ts +33 -0
  211. package/dist/publication/targets.d.ts.map +1 -0
  212. package/dist/publication/video.d.ts +5 -0
  213. package/dist/publication/video.d.ts.map +1 -0
  214. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  215. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  216. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  218. package/dist/record/fold-buckets.d.ts +95 -0
  219. package/dist/record/fold-buckets.d.ts.map +1 -0
  220. package/dist/record/fold-instance-buffer.d.ts +6 -0
  221. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  222. package/dist/record/frame-lighting.d.ts +1 -0
  223. package/dist/record/frame-lighting.d.ts.map +1 -1
  224. package/dist/record/frame-snapshot.d.ts +43 -9
  225. package/dist/record/frame-snapshot.d.ts.map +1 -1
  226. package/dist/record/frame.d.ts +15 -65
  227. package/dist/record/frame.d.ts.map +1 -1
  228. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  229. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  230. package/dist/record/gpu-timing.d.ts +8 -0
  231. package/dist/record/gpu-timing.d.ts.map +1 -1
  232. package/dist/record/helpers.d.ts +2 -2
  233. package/dist/record/helpers.d.ts.map +1 -1
  234. package/dist/record/main-pass-geometry.d.ts +22 -6
  235. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  236. package/dist/record/main-pass-material.d.ts +14 -10
  237. package/dist/record/main-pass-material.d.ts.map +1 -1
  238. package/dist/record/main-pass-sprite-draws.d.ts +3 -16
  239. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  240. package/dist/record/main-pass.d.ts +13 -2
  241. package/dist/record/main-pass.d.ts.map +1 -1
  242. package/dist/record/motion-blur-receipt.d.ts +11 -0
  243. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  244. package/dist/record/prepared-material-bindings.d.ts +3 -3
  245. package/dist/record/prepared-material-bindings.d.ts.map +1 -1
  246. package/dist/record/probe-blend-buffer.d.ts +16 -0
  247. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  248. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  249. package/dist/record/render-context.d.ts +24 -5
  250. package/dist/record/render-context.d.ts.map +1 -1
  251. package/dist/record/shadow-pass.d.ts +2 -0
  252. package/dist/record/shadow-pass.d.ts.map +1 -1
  253. package/dist/record/skybox-post-pass.d.ts +1 -1
  254. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  255. package/dist/record/sprite-instance-buffer.d.ts +31 -0
  256. package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
  257. package/dist/record/target-capture-graph.d.ts +19 -0
  258. package/dist/record/target-capture-graph.d.ts.map +1 -0
  259. package/dist/record/typed-frame-graph.d.ts +24 -15
  260. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  261. package/dist/record/view-ubo.d.ts +11 -3
  262. package/dist/record/view-ubo.d.ts.map +1 -1
  263. package/dist/record/volume-params.d.ts +9 -0
  264. package/dist/record/volume-params.d.ts.map +1 -0
  265. package/dist/recovery/render-system-candidate.d.ts +14 -4
  266. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  267. package/dist/reflection/record-owner.d.ts.map +1 -1
  268. package/dist/render-contract.d.ts +46 -5
  269. package/dist/render-contract.d.ts.map +1 -1
  270. package/dist/render-graph-primitives.d.ts.map +1 -1
  271. package/dist/render-pipeline.d.ts +103 -2
  272. package/dist/render-pipeline.d.ts.map +1 -1
  273. package/dist/render-system-extract-tail.d.ts +3 -2
  274. package/dist/render-system-extract-tail.d.ts.map +1 -1
  275. package/dist/render-system-extract.d.ts +18 -9
  276. package/dist/render-system-extract.d.ts.map +1 -1
  277. package/dist/render-system-presentation.d.ts +23 -0
  278. package/dist/render-system-presentation.d.ts.map +1 -0
  279. package/dist/render-system-producer-roots.d.ts +10 -0
  280. package/dist/render-system-producer-roots.d.ts.map +1 -0
  281. package/dist/render-system-projections.d.ts +3 -2
  282. package/dist/render-system-projections.d.ts.map +1 -1
  283. package/dist/render-system-residency.d.ts +12 -0
  284. package/dist/render-system-residency.d.ts.map +1 -0
  285. package/dist/render-system.d.ts +22 -21
  286. package/dist/render-system.d.ts.map +1 -1
  287. package/dist/scene/probe-blend.d.ts +27 -0
  288. package/dist/scene/probe-blend.d.ts.map +1 -1
  289. package/dist/scene/render-scene.d.ts +18 -7
  290. package/dist/scene/render-scene.d.ts.map +1 -1
  291. package/dist/scene/render-source.d.ts +42 -0
  292. package/dist/scene/render-source.d.ts.map +1 -0
  293. package/dist/scene/source-systems.d.ts +6 -0
  294. package/dist/scene/source-systems.d.ts.map +1 -0
  295. package/dist/ssao-buffers.d.ts +9 -0
  296. package/dist/ssao-buffers.d.ts.map +1 -1
  297. package/dist/surface/dynamic-input.d.ts +133 -0
  298. package/dist/surface/dynamic-input.d.ts.map +1 -0
  299. package/dist/surface/gpu-driven.d.ts +41 -0
  300. package/dist/surface/gpu-driven.d.ts.map +1 -0
  301. package/dist/surface/submission-observation.d.ts +136 -0
  302. package/dist/surface/submission-observation.d.ts.map +1 -0
  303. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  304. package/dist/systems/skin-palette-types.d.ts +10 -0
  305. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  306. package/dist/systems/transparent-dispatch.d.ts +2 -2
  307. package/dist/systems/transparent-dispatch.d.ts.map +1 -1
  308. package/dist/systems/transparent-sort-config.d.ts +2 -1
  309. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  310. package/dist/temporal/gpu.d.ts +13 -1
  311. package/dist/temporal/gpu.d.ts.map +1 -1
  312. package/dist/temporal/index.mjs +6 -7
  313. package/dist/temporal/inspection.d.ts.map +1 -1
  314. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  315. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  316. package/dist/transmission/single-layer-medium.d.ts +89 -0
  317. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  318. package/dist/typed-render-graph-primitives.d.ts +14 -2
  319. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  320. package/dist/volume/component.d.ts +9 -4
  321. package/dist/volume/component.d.ts.map +1 -1
  322. package/dist/volume/extract.d.ts +1 -1
  323. package/dist/volume/extract.d.ts.map +1 -1
  324. package/dist/volume/inspection.d.ts +2 -0
  325. package/dist/volume/inspection.d.ts.map +1 -1
  326. package/dist/volume/passes.d.ts +4 -1
  327. package/dist/volume/passes.d.ts.map +1 -1
  328. package/dist/volume/resources.d.ts.map +1 -1
  329. package/package.json +22 -21
  330. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  331. package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
  332. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  333. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  334. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  335. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  336. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  337. package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
  338. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  339. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  340. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  341. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +5 -6
  348. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  349. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  350. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  351. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  352. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  353. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  354. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  355. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  356. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  357. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  358. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  359. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  360. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  361. package/src/__tests__/instances-store.unit.test.ts +97 -305
  362. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  363. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
  364. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +145 -0
  365. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  366. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  367. package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
  368. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  369. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  370. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  371. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  372. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  373. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  374. package/src/__tests__/physical-clearcoat.integration.test.ts +66 -8
  375. package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
  376. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  377. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  378. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  379. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  380. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  381. package/src/__tests__/render-error-code-owner.test-d.ts +8 -0
  382. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  383. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  384. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  385. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  386. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  387. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  388. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  389. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  390. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  391. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  392. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -8
  393. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  394. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  395. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  396. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  397. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  398. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  399. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  400. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  401. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  402. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  403. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  404. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  405. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  406. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  407. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  408. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  409. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  410. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  411. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  412. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  413. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  414. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  415. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  416. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  417. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  418. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  419. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  420. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  421. package/src/assembly/backend-contract.ts +30 -0
  422. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  423. package/src/assembly/canvas-draw-guard.ts +11 -0
  424. package/src/assembly/cloud-shadow-entry.ts +22 -0
  425. package/src/assembly/device-feature-admission.ts +2 -2
  426. package/src/assembly/dynamic-geometry-host.ts +65 -37
  427. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  428. package/src/assembly/factory.ts +2 -30
  429. package/src/assembly/host-contract.ts +8 -5
  430. package/src/assembly/material/assembly.ts +25 -13
  431. package/src/assembly/material/pipeline-helpers.ts +53 -12
  432. package/src/assembly/material-shader-policy.ts +55 -0
  433. package/src/assembly/material-shader-prewarm.ts +21 -10
  434. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  435. package/src/assembly/recovery/renderer-recover.ts +50 -18
  436. package/src/assembly/render-feature-post-processes.ts +54 -0
  437. package/src/assembly/render-target-host.ts +57 -47
  438. package/src/assembly/renderer-facade.ts +7 -2
  439. package/src/assembly/renderer-feature-inspection.ts +8 -2
  440. package/src/assembly/renderer-frame-transaction.ts +23 -0
  441. package/src/assembly/renderer-inspection.ts +28 -0
  442. package/src/assembly/skin-palette-owner.ts +1 -1
  443. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  444. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  445. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  446. package/src/assembly/webgpu-ready.ts +116 -62
  447. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  448. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  449. package/src/assembly/webgpu-renderer.ts +303 -313
  450. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  451. package/src/barrel-distortion.ts +247 -0
  452. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  453. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  454. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  455. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  456. package/src/cloud/density.ts +600 -0
  457. package/src/cloud/extract.ts +110 -0
  458. package/src/cloud/feature.ts +1810 -0
  459. package/src/cloud/frame-context.ts +42 -0
  460. package/src/cloud/inspection.ts +130 -0
  461. package/src/cloud/optics.ts +285 -0
  462. package/src/cloud/parameters.ts +255 -0
  463. package/src/cloud/resources.ts +122 -0
  464. package/src/cloud/shadow.ts +167 -0
  465. package/src/cloud/temporal.ts +226 -0
  466. package/src/components/barrel-distortion.ts +46 -0
  467. package/src/components/cloud-layer.ts +47 -0
  468. package/src/components/index.ts +2 -0
  469. package/src/components/instances.ts +18 -45
  470. package/src/components/sprite-instances.ts +1 -1
  471. package/src/construct-renderer.ts +1 -1
  472. package/src/device/gpu-residency.ts +26 -25
  473. package/src/dynamic-geometry.ts +12 -1
  474. package/src/errors/cloud.ts +103 -0
  475. package/src/errors/render.ts +47 -8
  476. package/src/examples/single-layer-medium-surface.ts +59 -0
  477. package/src/extract/camera.ts +15 -1
  478. package/src/extract/contracts.ts +5 -0
  479. package/src/extract/material-context.ts +21 -0
  480. package/src/features/barrel-distortion.ts +172 -0
  481. package/src/features/error-reporting.ts +26 -6
  482. package/src/features/host.ts +128 -19
  483. package/src/features/plan.ts +10 -0
  484. package/src/features/render-graph-contribution.ts +9 -0
  485. package/src/features/render-graph-raster.ts +45 -3
  486. package/src/features/targets.ts +66 -0
  487. package/src/features/types.ts +51 -0
  488. package/src/fullscreen-post-process-pass.ts +41 -9
  489. package/src/glyph-text-layout-system.ts +2 -2
  490. package/src/gpu-dirty-ranges.ts +48 -0
  491. package/src/gpu-driven/batch-topology.ts +53 -0
  492. package/src/gpu-driven/material-artifacts.ts +33 -25
  493. package/src/gpu-driven/prepared-draw.ts +12 -4
  494. package/src/gpu-driven/production-raster-material.ts +1894 -0
  495. package/src/gpu-driven/production-raster.ts +825 -784
  496. package/src/gpu-driven/resource-allocation.ts +142 -0
  497. package/src/gpu-driven/shadow-ownership.ts +71 -0
  498. package/src/gpu-driven/view-gpu.ts +164 -10
  499. package/src/gpu-scene.ts +75 -84
  500. package/src/hdrp-buffers.ts +4 -3
  501. package/src/ibl/frame-resources.ts +0 -1
  502. package/src/ibl/skylight-bind-group.ts +62 -32
  503. package/src/index.ts +205 -9
  504. package/src/inspection-types.ts +162 -0
  505. package/src/instance-buffer-cache.ts +4 -4
  506. package/src/instances.ts +152 -569
  507. package/src/pbr-pipeline.ts +230 -30
  508. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  509. package/src/pipeline/standard-forward-lane.ts +313 -57
  510. package/src/pipeline/standard-output/graph.ts +8 -2
  511. package/src/pipeline/standard-output/lut-gpu.ts +3 -3
  512. package/src/pipeline/standard-output/resources.ts +2 -2
  513. package/src/pipeline/standard-output/types.ts +12 -1
  514. package/src/pipeline/standard-pipeline.ts +291 -18
  515. package/src/pipeline/standard-post.ts +90 -24
  516. package/src/pipeline-builder.ts +1 -1
  517. package/src/plugin.ts +4 -0
  518. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  519. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  520. package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
  521. package/src/publication/__tests__/features.integration.test.ts +122 -0
  522. package/src/publication/__tests__/programs.unit.test.ts +25 -0
  523. package/src/publication/__tests__/publication.integration.test.ts +370 -0
  524. package/src/publication/__tests__/targets.integration.test.ts +120 -0
  525. package/src/publication/__tests__/video.browser.test.ts +50 -0
  526. package/src/publication/contract.ts +104 -0
  527. package/src/publication/dependencies.ts +54 -0
  528. package/src/publication/prepare-geometry.ts +94 -0
  529. package/src/publication/programs.ts +45 -0
  530. package/src/publication/publisher.ts +618 -0
  531. package/src/publication/receiver.ts +297 -0
  532. package/src/publication/resource-scope.ts +31 -0
  533. package/src/publication/targets.ts +182 -0
  534. package/src/publication/video.ts +33 -0
  535. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  536. package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
  537. package/src/record/__tests__/sprite-material-abi.unit.test.ts +9 -11
  538. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  539. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  540. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  541. package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
  542. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  543. package/src/record/barrel-distortion-frame.ts +110 -0
  544. package/src/record/dynamic-geometry-consumption.ts +39 -9
  545. package/src/record/fold-buckets.ts +855 -0
  546. package/src/record/fold-instance-buffer.ts +51 -0
  547. package/src/record/frame-lighting.ts +36 -2
  548. package/src/record/frame-snapshot.ts +45 -9
  549. package/src/record/frame.ts +258 -1105
  550. package/src/record/gpu-draw-receipts.ts +38 -0
  551. package/src/record/gpu-timing.ts +48 -5
  552. package/src/record/helpers.ts +2 -2
  553. package/src/record/main-pass-geometry.ts +272 -84
  554. package/src/record/main-pass-material.ts +102 -36
  555. package/src/record/main-pass-sprite-draws.ts +13 -217
  556. package/src/record/main-pass.ts +164 -27
  557. package/src/record/motion-blur-receipt.ts +91 -0
  558. package/src/record/prepared-material-bindings.ts +11 -6
  559. package/src/record/probe-blend-buffer.ts +180 -0
  560. package/src/record/recovery-pipeline.ts +35 -3
  561. package/src/record/render-context.ts +41 -5
  562. package/src/record/shadow-pass.ts +30 -4
  563. package/src/record/skybox-post-pass.ts +28 -4
  564. package/src/record/sprite-instance-buffer.ts +155 -0
  565. package/src/record/target-capture-graph.ts +258 -0
  566. package/src/record/typed-frame-graph.ts +776 -340
  567. package/src/record/view-ubo.ts +27 -4
  568. package/src/record/volume-params.ts +225 -0
  569. package/src/recovery/render-system-candidate.ts +243 -50
  570. package/src/reflection/record-owner.ts +7 -3
  571. package/src/render-contract.ts +54 -5
  572. package/src/render-graph-primitives.ts +7 -1
  573. package/src/render-pipeline.ts +130 -0
  574. package/src/render-system-extract-tail.ts +90 -78
  575. package/src/render-system-extract.ts +76 -76
  576. package/src/render-system-presentation.ts +56 -0
  577. package/src/render-system-producer-roots.ts +96 -0
  578. package/src/render-system-projections.ts +3 -2
  579. package/src/render-system-residency.ts +159 -0
  580. package/src/render-system.ts +421 -408
  581. package/src/scene/probe-blend.ts +96 -4
  582. package/src/scene/render-scene.ts +416 -337
  583. package/src/scene/render-source.ts +90 -0
  584. package/src/scene/source-systems.ts +33 -0
  585. package/src/ssao-buffers.ts +95 -2
  586. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  587. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  588. package/src/surface/dynamic-input.ts +658 -0
  589. package/src/surface/gpu-driven.ts +147 -0
  590. package/src/surface/submission-observation.ts +517 -0
  591. package/src/systems/skin-palette-allocator.ts +5 -1
  592. package/src/systems/skin-palette-types.ts +11 -0
  593. package/src/systems/transparent-dispatch.ts +2 -2
  594. package/src/systems/transparent-sort-config.ts +3 -1
  595. package/src/temporal/gpu.ts +101 -17
  596. package/src/temporal/inspection.ts +7 -1
  597. package/src/temporal/standard-scene-data.ts +5 -0
  598. package/src/temporal/target-coverage-attachment.ts +4 -0
  599. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  600. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  601. package/src/transmission/single-layer-medium.ts +322 -0
  602. package/src/typed-render-graph-primitives.ts +70 -2
  603. package/src/volume/component.ts +10 -9
  604. package/src/volume/extract.ts +11 -5
  605. package/src/volume/inspection.ts +3 -0
  606. package/src/volume/passes.ts +87 -4
  607. package/src/volume/resources.ts +2 -1
  608. package/dist/chunk-3RTCJTH4.mjs +0 -1610
  609. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  610. package/dist/chunk-BLXGONR2.mjs.map +0 -1
  611. package/dist/chunk-ILQ5MEZF.mjs +0 -32
  612. package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
  613. package/dist/chunk-LEAXOMYJ.mjs.map +0 -1
  614. package/dist/chunk-NB2S7ZRX.mjs +0 -1783
  615. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  616. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  617. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  618. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  619. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  620. package/dist/chunk-PLAXOOX5.mjs +0 -1907
  621. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  622. package/dist/chunk-RXZ3RGOU.mjs +0 -53
  623. package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
  624. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -17,6 +17,7 @@ import type {
17
17
  PreparedGraphicsResolver,
18
18
  PreparedGraphicsResourceLease,
19
19
  } from '../prepare/prepared-graphics-resolver';
20
+ import type { CameraSnapshot } from '../render-contract';
20
21
  import { isSceneDataTarget, type SceneDataTarget } from '../temporal/scene-data';
21
22
  import { createSceneDataCatalog, type SceneDataCatalog } from '../temporal/scene-data-catalog';
22
23
  import {
@@ -114,6 +115,7 @@ export interface RenderFeaturePlanExecutionPass {
114
115
  export interface RenderFeaturePlanExecution {
115
116
  readonly featureIdentity: string;
116
117
  readonly order: number;
118
+ readonly placement?: import('./types').RenderFeaturePlacement;
117
119
  readonly passes: readonly RenderFeaturePlanExecutionPass[];
118
120
  }
119
121
 
@@ -131,9 +133,13 @@ export interface RenderFeatureStageEvent {
131
133
  }
132
134
 
133
135
  export interface RenderFeatureFrameInput {
136
+ readonly publishedFeatures?: readonly { readonly identity: string; readonly data: unknown }[];
137
+ readonly onFeatureSourceSubmitted?: (identity: string, feedback: unknown) => void;
134
138
  readonly worlds: readonly import('@forgeax/engine-ecs').World[];
135
139
  readonly owner: number;
136
140
  readonly frameNumber: number;
141
+ /** Renderer-selected display camera forwarded to feature extraction. */
142
+ readonly selectedCamera?: CameraSnapshot;
137
143
  /** Physical render extent for bounded feature dispatch sizing. */
138
144
  readonly frameSize?: { readonly width: number; readonly height: number };
139
145
  readonly visibilitySnapshots?: readonly RenderFeatureWorldVisibilitySnapshot[];
@@ -144,6 +150,8 @@ export interface RenderFeatureFrameInput {
144
150
  readonly sceneData?: SceneDataCatalog;
145
151
  readonly generation?: number;
146
152
  readonly caps: Readonly<RhiCaps>;
153
+ /** Normal frame-owner facts shared with producer extraction. */
154
+ readonly frame?: import('./types').RenderFeatureFrameContext;
147
155
  /** Renderer-owned material binding contract projection for producer plans. */
148
156
  readonly materialShaderBindingContract?: (
149
157
  materialShaderId: string,
@@ -175,6 +183,8 @@ export interface RenderFeatureFrameResult {
175
183
  readonly errors: readonly RenderError[];
176
184
  readonly plans: readonly RenderFeaturePlannedFrame[];
177
185
  readonly fullscreenEffects: ReadonlyMap<string, PostProcessShaderEntry>;
186
+ /** Public Standard post-effect identities; graph-local fullscreen resources are not included. */
187
+ readonly postProcessIdentities: readonly string[];
178
188
  readonly preparedResourceBatches: readonly RenderFeaturePreparedResourceBatch[];
179
189
  /**
180
190
  * True only when the current graph resolves a transient graphics lease.
@@ -223,6 +233,8 @@ export interface RenderFeatureHost {
223
233
  recover(input: RenderFeatureRecoverInput): Result<void, RenderError>;
224
234
  createRecoveryRoot(scope: DeviceScope): LifecycleResourceSpec<unknown>;
225
235
  diagnostics(): readonly RenderFeatureDiagnostics[];
236
+ /** Retain an explicitly producer-published detached inspection value. */
237
+ setInspection(identity: string, inspection: unknown): void;
226
238
  /** Subscribe to lifecycle projection changes; unchanged active frames are silent. */
227
239
  subscribeDiagnostics(listener: () => void): () => void;
228
240
  /** Detached signature and prepared-resource accounting for diagnostics. */
@@ -269,6 +281,7 @@ interface FeatureSlot {
269
281
  readonly preparedStore: PreparedGraphicsStore;
270
282
  status: RenderFeatureStatus;
271
283
  latestError: RenderFeatureErrorDescriptor | undefined;
284
+ latestInspection?: unknown;
272
285
  }
273
286
 
274
287
  function freezeError(error: RenderFeatureErrorDescriptor): RenderFeatureErrorDescriptor {
@@ -291,6 +304,7 @@ function freezeDiagnostics(slot: FeatureSlot): RenderFeatureDiagnostics {
291
304
  order: slot.order,
292
305
  status: slot.status,
293
306
  latestError: slot.latestError === undefined ? undefined : freezeError(slot.latestError),
307
+ ...(slot.latestInspection === undefined ? {} : { inspection: slot.latestInspection }),
294
308
  });
295
309
  }
296
310
 
@@ -320,6 +334,16 @@ function missingCapability(
320
334
  return feature.requiredCapabilities?.find((capability) => caps[capability] !== true);
321
335
  }
322
336
 
337
+ /**
338
+ * Capability declarations gate work that the current plan actually admits.
339
+ * A producer is still allowed to extract and return an empty plan when its
340
+ * authored feature is disabled; that path must remain allocation-free on a
341
+ * backend which cannot support the optional feature.
342
+ */
343
+ function hasActivePlan(plan: RenderFeaturePlan): boolean {
344
+ return plan.resources.length > 0 || plan.passes.length > 0;
345
+ }
346
+
323
347
  function createPreparedGraphicsPrepare(
324
348
  transaction: PreparedGraphicsTransaction,
325
349
  ): RenderFeatureGraphicsPrepare {
@@ -346,6 +370,9 @@ function resolveGraphicsSnapshot(
346
370
  resolver: PreparedGraphicsResolver,
347
371
  descriptor: import('./prepared-graphics').RenderFeatureGraphicsPassDescriptor,
348
372
  generation: number,
373
+ resolveGpuResource?: (
374
+ name: string,
375
+ ) => import('./prepared-gpu-work').RenderFeatureResolvedGpuBuffer | undefined,
349
376
  ): Result<PreparedGraphicsResolvedSnapshot, RenderError> {
350
377
  const resources = new Map<
351
378
  object,
@@ -364,6 +391,7 @@ function resolveGraphicsSnapshot(
364
391
  ...(resolver.resolveGpuBuffer === undefined
365
392
  ? {}
366
393
  : { resolveGpuBuffer: resolver.resolveGpuBuffer }),
394
+ ...(resolveGpuResource === undefined ? {} : { resolveGpuResource }),
367
395
  });
368
396
  }
369
397
 
@@ -971,6 +999,7 @@ function projectPlanPasses(
971
999
  return ok({
972
1000
  featureIdentity: slot.feature.identity,
973
1001
  order: slot.order,
1002
+ ...(slot.feature.placement === undefined ? {} : { placement: slot.feature.placement }),
974
1003
  passes: Object.freeze(projected),
975
1004
  });
976
1005
  }
@@ -1330,6 +1359,13 @@ class FeatureHostImpl implements RenderFeatureHost {
1330
1359
  return Object.freeze(this.slots.map(freezeDiagnostics));
1331
1360
  }
1332
1361
 
1362
+ /** Retain only an explicitly producer-published detached inspection value. */
1363
+ setInspection(identity: string, inspection: unknown): void {
1364
+ const slot = findSlot(this.slots, identity);
1365
+ if (slot === undefined || slot.status === 'disposed') return;
1366
+ slot.latestInspection = inspection;
1367
+ }
1368
+
1333
1369
  subscribeDiagnostics(listener: () => void): () => void {
1334
1370
  this.diagnosticsListeners.add(listener);
1335
1371
  return () => this.diagnosticsListeners.delete(listener);
@@ -1360,6 +1396,7 @@ export function runRenderFeatureFrame(
1360
1396
  const errors: RenderError[] = [];
1361
1397
  const plans: RenderFeaturePlannedFrame[] = [];
1362
1398
  const fullscreenEffects = new Map<string, PostProcessShaderEntry>();
1399
+ const postProcessIdentities = new Set<string>();
1363
1400
  const preparedResourceBatches: RenderFeaturePreparedResourceBatch[] = [];
1364
1401
  let requiresPreparedResourceKey = false;
1365
1402
  const hiddenEntityReports: RenderFeatureHiddenEntityReport[] = [
@@ -1370,17 +1407,18 @@ export function runRenderFeatureFrame(
1370
1407
  const diagnostics = host.diagnostics();
1371
1408
  for (const [order, feature] of host.features.entries()) {
1372
1409
  const diagnostic = diagnostics[order];
1373
- if (diagnostic?.status === 'disabled' || diagnostic?.status === 'disposed') continue;
1374
- const missing = missingCapability(feature, input.caps);
1375
- if (missing !== undefined) {
1376
- const capabilityError = new RenderFeatureCapabilityMissingError(
1377
- feature.identity,
1378
- order,
1379
- missing,
1380
- );
1381
- errors.push(capabilityError);
1382
- host.setStatus(feature.identity, 'disabled', errorDescriptor(capabilityError));
1383
- continue;
1410
+ if (diagnostic?.status === 'disposed') continue;
1411
+ // Preserve the existing recovery contract for a capability-disabled
1412
+ // feature once the device becomes capable: an explicit host.recover()
1413
+ // still re-admits it. While the capability is absent, however, rerun the
1414
+ // producer so a camera/world can disable its authored plan and recover to
1415
+ // an empty, zero-resource frame without a second manager.
1416
+ if (diagnostic?.status === 'disabled') {
1417
+ const diagnosticError = diagnostic.latestError;
1418
+ const missing = missingCapability(feature, input.caps);
1419
+ if (diagnosticError?.code !== 'render-feature-capability-missing' || missing === undefined) {
1420
+ continue;
1421
+ }
1384
1422
  }
1385
1423
  const slot: FeatureSlot = {
1386
1424
  feature,
@@ -1391,6 +1429,9 @@ export function runRenderFeatureFrame(
1391
1429
  latestError: undefined,
1392
1430
  };
1393
1431
  const identity = slot.feature.identity;
1432
+ for (const postProcess of feature.requiredFullscreenPostProcesses ?? []) {
1433
+ postProcessIdentities.add(postProcess.identity);
1434
+ }
1394
1435
  const transaction = host.beginPreparedFrame(identity, input.generation ?? 0);
1395
1436
  if (transaction === undefined) continue;
1396
1437
  const graphics = createPreparedGraphicsPrepare(transaction);
@@ -1404,6 +1445,9 @@ export function runRenderFeatureFrame(
1404
1445
  worlds: input.worlds,
1405
1446
  owner: input.owner,
1406
1447
  frameNumber: input.frameNumber,
1448
+ ...(input.selectedCamera === undefined ? {} : { selectedCamera: input.selectedCamera }),
1449
+ caps: input.caps,
1450
+ ...(input.frame === undefined ? {} : { frame: input.frame }),
1407
1451
  reportHiddenEntity: (report) => featureHiddenEntityReports.push(report),
1408
1452
  ...(input.visibilitySnapshots === undefined
1409
1453
  ? {}
@@ -1412,7 +1456,10 @@ export function runRenderFeatureFrame(
1412
1456
  const extracted = invokeStage(
1413
1457
  slot,
1414
1458
  'extract',
1415
- () => slot.feature.extract(extractContext),
1459
+ () => {
1460
+ const published = input.publishedFeatures?.find((row) => row.identity === identity);
1461
+ return published === undefined ? slot.feature.extract(extractContext) : ok(published.data);
1462
+ },
1416
1463
  stageEvents,
1417
1464
  errors,
1418
1465
  );
@@ -1421,6 +1468,16 @@ export function runRenderFeatureFrame(
1421
1468
  host.setStatus(identity, 'failed', slot.latestError);
1422
1469
  continue;
1423
1470
  }
1471
+ if (
1472
+ typeof extracted.value === 'object' &&
1473
+ extracted.value !== null &&
1474
+ 'inspection' in extracted.value
1475
+ ) {
1476
+ host.setInspection(
1477
+ identity,
1478
+ (extracted.value as { readonly inspection?: unknown }).inspection,
1479
+ );
1480
+ }
1424
1481
 
1425
1482
  const targets = logicalTargets(input.targets ?? []);
1426
1483
  const sceneData =
@@ -1466,21 +1523,43 @@ export function runRenderFeatureFrame(
1466
1523
  host.setStatus(identity, 'failed', slot.latestError);
1467
1524
  continue;
1468
1525
  }
1526
+ const missing = missingCapability(feature, input.caps);
1527
+ if (missing !== undefined && hasActivePlan(frozen.value)) {
1528
+ const capabilityError = new RenderFeatureCapabilityMissingError(identity, order, missing);
1529
+ errors.push(capabilityError);
1530
+ transaction.abort();
1531
+ host.setStatus(identity, 'disabled', errorDescriptor(capabilityError));
1532
+ continue;
1533
+ }
1469
1534
  const plannedFrame: RenderFeaturePlannedFrame = Object.freeze({
1470
1535
  featureIdentity: identity,
1471
1536
  generation: transaction.generation,
1472
1537
  signature:
1473
1538
  host.recordPlanSignature?.(identity, frozen.value) ??
1474
1539
  renderFeaturePlanSignature(frozen.value),
1540
+ ...(feature.placement === undefined ? {} : { placement: feature.placement }),
1475
1541
  plan: frozen.value,
1476
1542
  });
1477
1543
  for (const resource of frozen.value.resources) {
1478
1544
  if (resource.kind !== 'fullscreen-program') continue;
1479
- fullscreenEffects.set(identity, {
1545
+ const entry = {
1480
1546
  source: resource.source,
1547
+ ...(resource.fragmentEntryPoint === undefined
1548
+ ? {}
1549
+ : { fragmentEntryPoint: resource.fragmentEntryPoint }),
1481
1550
  ...(resource.reads === undefined ? {} : { reads: resource.reads }),
1551
+ ...(resource.usesView === undefined ? {} : { usesView: resource.usesView }),
1552
+ ...(resource.storageBindings === undefined
1553
+ ? {}
1554
+ : { storageBindings: resource.storageBindings }),
1482
1555
  ...(resource.params === undefined ? {} : { params: resource.params }),
1483
- });
1556
+ } satisfies PostProcessShaderEntry;
1557
+ // A feature may expose more than one graph-local fullscreen producer
1558
+ // (the cloud display composite and its shadow map). Keep each resource
1559
+ // addressable by its declared name and retain the feature identity alias
1560
+ // for the original public post-process route.
1561
+ fullscreenEffects.set(resource.name, entry);
1562
+ if (!fullscreenEffects.has(identity)) fullscreenEffects.set(identity, entry);
1484
1563
  }
1485
1564
  const prepared = preparePlanResources(slot, frozen.value, graphics, gpu, input.targets ?? []);
1486
1565
  if (!prepared.ok) {
@@ -1512,7 +1591,33 @@ export function runRenderFeatureFrame(
1512
1591
  : (descriptor: import('./prepared-graphics').RenderFeatureGraphicsPassDescriptor) => {
1513
1592
  // A pending pass can be skipped while earlier passes remain usable.
1514
1593
  // Keep their shared resolver leases alive until submission retires them.
1515
- return resolveGraphicsSnapshot(resolver, descriptor, transaction.generation);
1594
+ const resolveGpuResource = (name: string) => {
1595
+ const owned = prepared.value.buffers.get(name);
1596
+ const borrowed = prepared.value.preparedGpuResources.get(name);
1597
+ const reference =
1598
+ owned ?? (borrowed?.kind === 'buffer' ? borrowed.reference : undefined);
1599
+ return reference === undefined ? undefined : gpu?.resolveBuffer(reference);
1600
+ };
1601
+ const resolved = resolveGraphicsSnapshot(
1602
+ resolver,
1603
+ descriptor,
1604
+ transaction.generation,
1605
+ resolveGpuResource,
1606
+ );
1607
+ // A pending pipeline is a retryable partial frame. The resolver
1608
+ // leases cover resources used by earlier ready passes and must
1609
+ // stay retained until the submitted batch retires; only terminal
1610
+ // resolution failures release them here.
1611
+ if (
1612
+ !resolved.ok &&
1613
+ !(
1614
+ resolved.error instanceof RenderFeaturePreparationFailedError &&
1615
+ resolved.error.detail.reason === 'pipeline-pending'
1616
+ )
1617
+ ) {
1618
+ resolver.release();
1619
+ }
1620
+ return resolved;
1516
1621
  };
1517
1622
  const releaseResolver = (): void => {
1518
1623
  if (resolver !== undefined) resolver.release();
@@ -1555,11 +1660,14 @@ export function runRenderFeatureFrame(
1555
1660
  continue;
1556
1661
  }
1557
1662
  planExecutionProjections.set(plannedFrame, projected.value);
1558
- if (feature.onFrameSubmitted !== undefined) {
1663
+ if (feature.onFrameSubmitted !== undefined || feature.onSourceFrameSubmitted !== undefined) {
1559
1664
  submissionSensitivePlans.add(plannedFrame);
1560
- submissionAcknowledgments.set(plannedFrame, () =>
1561
- feature.onFrameSubmitted?.(extracted.value, projected.value),
1562
- );
1665
+ submissionAcknowledgments.set(plannedFrame, () => {
1666
+ feature.onFrameSubmitted?.(extracted.value, projected.value);
1667
+ if (input.publishedFeatures?.some((row) => row.identity === identity))
1668
+ input.onFeatureSourceSubmitted?.(identity, declared.value.sourceFeedback);
1669
+ else feature.onSourceFrameSubmitted?.(extracted.value, declared.value.sourceFeedback);
1670
+ });
1563
1671
  }
1564
1672
  plans.push(plannedFrame);
1565
1673
  if (feature.onFrameAborted !== undefined) {
@@ -1577,6 +1685,7 @@ export function runRenderFeatureFrame(
1577
1685
  errors,
1578
1686
  plans,
1579
1687
  fullscreenEffects,
1688
+ postProcessIdentities: Object.freeze([...postProcessIdentities]),
1580
1689
  preparedResourceBatches,
1581
1690
  requiresPreparedResourceKey,
1582
1691
  hiddenEntityReports: mergeHiddenEntityReports(hiddenEntityReports),
@@ -51,7 +51,13 @@ export interface RenderFeatureFullscreenProgramDeclaration {
51
51
  readonly kind: 'fullscreen-program';
52
52
  readonly name: string;
53
53
  readonly source: string;
54
+ /** Optional fragment entry point when one WGSL module owns multiple passes. */
55
+ readonly fragmentEntryPoint?: string;
54
56
  readonly reads?: readonly RenderFeatureFullscreenRead[];
57
+ /** Bind the renderer-owned View group at group(0) for camera reconstruction. */
58
+ readonly usesView?: boolean;
59
+ /** Read-only storage buffers appended after the regular color/depth reads. */
60
+ readonly storageBindings?: readonly number[];
55
61
  readonly params?: {
56
62
  readonly byteSize: number;
57
63
  readonly defaultValue: Uint8Array;
@@ -231,6 +237,8 @@ export type RenderFeaturePassDeclaration =
231
237
  * access is derived from these roles rather than duplicated as reads/writes.
232
238
  */
233
239
  export interface RenderFeaturePlan {
240
+ /** Source acknowledgment facts; never part of GPU resource or graph identity. */
241
+ readonly sourceFeedback?: unknown;
234
242
  readonly resources: readonly RenderFeatureResourceDeclaration[];
235
243
  readonly passes: readonly RenderFeaturePassDeclaration[];
236
244
  }
@@ -275,6 +283,8 @@ export interface RenderFeaturePlannedFrame {
275
283
  readonly generation: number;
276
284
  readonly signature: string;
277
285
  readonly plan: RenderFeaturePlan;
286
+ /** Placement selected by the installed feature; omitted means the legacy post stage. */
287
+ readonly placement?: import('./types').RenderFeaturePlacement;
278
288
  }
279
289
 
280
290
  export interface RenderFeatureDerivedAccess {
@@ -19,6 +19,7 @@ import {
19
19
  resolveRenderFeatureDrawBuffers,
20
20
  } from './render-graph-raster';
21
21
  import { createRenderFeatureGraphBufferState } from './render-graph-resources';
22
+ import type { RenderFeaturePlacement } from './types';
22
23
 
23
24
  export function createRenderFeatureProjectionState() {
24
25
  return {
@@ -141,6 +142,10 @@ export function projectRenderFeaturePlans<FrameCtx extends RenderGraphFrame>(
141
142
  readonly reportError?: ((error: RenderError) => void) | undefined;
142
143
  readonly resolveStandardLighting?: RenderFeatureLightingResolver<FrameCtx> | undefined;
143
144
  readonly standardSurfaceAccesses?: readonly GraphAccess[] | undefined;
145
+ /** Restrict projection to one Standard graph placement. */
146
+ readonly placement?: RenderFeaturePlacement | undefined;
147
+ /** Restrict projection to the named passes for a multi-stage feature. */
148
+ readonly passNames?: ReadonlySet<string> | undefined;
144
149
  readonly state?: ReturnType<typeof createRenderFeatureProjectionState>;
145
150
  },
146
151
  ): Result<void, RenderGraphError | RenderError> {
@@ -162,7 +167,11 @@ export function projectRenderFeaturePlans<FrameCtx extends RenderGraphFrame>(
162
167
  options.standardSurfaceAccesses,
163
168
  );
164
169
  for (const execution of executions) {
170
+ if (options.placement !== undefined && (execution.placement ?? 'post') !== options.placement) {
171
+ continue;
172
+ }
165
173
  for (const pass of execution.passes) {
174
+ if (options.passNames !== undefined && !options.passNames.has(pass.name)) continue;
166
175
  if (state.projected.has(pass)) continue;
167
176
  if (pass.shadowCaster)
168
177
  return err(
@@ -57,6 +57,7 @@ export type RenderFeatureGraphBindingsResolver<FrameCtx extends RenderGraphFrame
57
57
  readonly binding: Extract<PreparedGraphicsResolvedResource, { readonly kind: 'bindings' }>;
58
58
  readonly resources: GraphResourceResolver;
59
59
  readonly resolveTarget: RenderFeatureGraphTargetResolver;
60
+ readonly resolveGpuResource?: (name: string) => RenderFeatureResolvedGpuBuffer | undefined;
60
61
  }) => RenderFeatureGraphBindingsResolution | undefined;
61
62
 
62
63
  export type RenderFeatureLightingResolver<FrameCtx extends RenderGraphFrame> = (
@@ -275,6 +276,32 @@ export class RenderFeatureRasterGraphProjection<FrameCtx extends RenderGraphFram
275
276
  accesses.push({ resource: handle, usage: 'indirect-read' } as const);
276
277
  }
277
278
 
279
+ // Feature-owned fullscreen/material bind groups may carry a read-only
280
+ // storage buffer (for example the bounded procedural cloud cache). Import
281
+ // it into the same graph so the compute producer is ordered before the
282
+ // raster consumer and the buffer lease follows queue retirement.
283
+ for (const draw of descriptor.draws) {
284
+ for (const reference of draw.bindings) {
285
+ const binding = resolved(snapshot, reference);
286
+ const names =
287
+ binding?.kind === 'bindings' ? binding.descriptor?.values.storageBuffers : undefined;
288
+ if (!Array.isArray(names)) continue;
289
+ for (const name of names) {
290
+ if (typeof name !== 'string') continue;
291
+ const physical = snapshot.resolveGpuResource?.(name);
292
+ if (physical === undefined) continue;
293
+ const imported = importRenderFeatureGraphBuffer(
294
+ this.builder,
295
+ this.buffers,
296
+ `${name}.${featureIdentity}.${order}`,
297
+ physical,
298
+ );
299
+ if (!imported.ok) return imported;
300
+ accesses.push({ resource: imported.value, usage: 'storage-read' } as const);
301
+ }
302
+ }
303
+ }
304
+
278
305
  return this.builder.addRasterPass(name, {
279
306
  accesses,
280
307
  colorAttachments: colors,
@@ -377,9 +404,24 @@ export class RenderFeatureRasterGraphProjection<FrameCtx extends RenderGraphFram
377
404
  pass.setBindGroup(0, shadowView, [0, 0]);
378
405
  continue;
379
406
  }
380
- const resolvedBindings =
381
- binding.handle ??
382
- this.resolveBindings?.({ frame, binding, resources, resolveTarget: this.resolveTarget });
407
+ // Fullscreen feature bindings contain graph-owned texture views and a
408
+ // per-frame params UBO. Resolve them at execution time so a retained
409
+ // graph still follows the current post-process input and authored
410
+ // parameters; material/view bindings remain safely cached.
411
+ const resolvedBindings = (() => {
412
+ const resolve = () =>
413
+ this.resolveBindings?.({
414
+ frame,
415
+ binding,
416
+ resources,
417
+ resolveTarget: this.resolveTarget,
418
+ ...(snapshot.resolveGpuResource === undefined
419
+ ? {}
420
+ : { resolveGpuResource: snapshot.resolveGpuResource }),
421
+ });
422
+ if (binding.descriptor?.values.fullscreen === true) return resolve();
423
+ return binding.handle ?? resolve();
424
+ })();
383
425
  const handle =
384
426
  resolvedBindings !== undefined &&
385
427
  typeof resolvedBindings === 'object' &&
@@ -55,6 +55,8 @@ export function resolveStandardRenderFeatureTargets(input: {
55
55
  readonly storageBuffer: boolean;
56
56
  readonly multisample: boolean;
57
57
  readonly colorAttachmentFormat: TextureFormat;
58
+ /** Expose cloud history aliases only while a CloudLayer is authored. */
59
+ readonly cloudHistory?: boolean;
58
60
  }): readonly RenderFeatureTargetHandle[] {
59
61
  const sampleCount: 1 | 4 = input.antialias === 'msaa' && input.multisample ? 4 : 1;
60
62
  // Standard always exposes the scene to features as a linear float target;
@@ -91,5 +93,69 @@ export function resolveStandardRenderFeatureTargets(input: {
91
93
  format: colorFormat,
92
94
  sampleCount: 1,
93
95
  }),
96
+ // A graph-owned, single-sample map produced before direct-solar lighting.
97
+ // The logical handle lets the feature plan validate its producer before
98
+ // the Standard pipeline allocates the concrete texture.
99
+ createRenderFeatureTarget({
100
+ name: 'cloud-shadow',
101
+ kind: 'scene-color',
102
+ format: 'rgba16float',
103
+ sampleCount: 1,
104
+ }),
105
+ // These are declarative aliases only. Standard allocates the actual
106
+ // linear-LDR ping-pong target at the ordered post stage and resolves these
107
+ // names through `contributeFeatures` when that stage is reached.
108
+ createRenderFeatureTarget({
109
+ name: 'barrel-input',
110
+ kind: 'scene-color',
111
+ format: 'rgba16float',
112
+ sampleCount: 1,
113
+ }),
114
+ createRenderFeatureTarget({
115
+ name: 'barrel-output',
116
+ kind: 'scene-color',
117
+ format: 'rgba16float',
118
+ sampleCount: 1,
119
+ }),
120
+ ...(input.cloudHistory === true
121
+ ? [
122
+ createRenderFeatureTarget({
123
+ name: 'cloud-history-radiance-previous',
124
+ kind: 'scene-color',
125
+ format: 'rgba16float',
126
+ sampleCount: 1,
127
+ }),
128
+ createRenderFeatureTarget({
129
+ name: 'cloud-history-radiance-current',
130
+ kind: 'scene-color',
131
+ format: 'rgba16float',
132
+ sampleCount: 1,
133
+ }),
134
+ createRenderFeatureTarget({
135
+ name: 'cloud-history-transmittance-previous',
136
+ kind: 'scene-color',
137
+ format: 'rgba16float',
138
+ sampleCount: 1,
139
+ }),
140
+ createRenderFeatureTarget({
141
+ name: 'cloud-history-transmittance-current',
142
+ kind: 'scene-color',
143
+ format: 'rgba16float',
144
+ sampleCount: 1,
145
+ }),
146
+ createRenderFeatureTarget({
147
+ name: 'cloud-history-depth-previous',
148
+ kind: 'scene-color',
149
+ format: 'rgba16float',
150
+ sampleCount: 1,
151
+ }),
152
+ createRenderFeatureTarget({
153
+ name: 'cloud-history-depth-current',
154
+ kind: 'scene-color',
155
+ format: 'rgba16float',
156
+ sampleCount: 1,
157
+ }),
158
+ ]
159
+ : []),
94
160
  ];
95
161
  }
@@ -4,6 +4,7 @@ import type { RhiCaps } from '@forgeax/engine-rhi';
4
4
  import type { Result } from '@forgeax/engine-types';
5
5
  import type { RenderError, RenderFeatureErrorDescriptor } from '../errors/render';
6
6
  import type { VisibilitySnapshot } from '../extract/visibility';
7
+ import type { CameraSnapshot } from '../render-contract';
7
8
  import type { RenderFeaturePlan, RenderFeaturePlanContext } from './plan';
8
9
  import type { RenderFeatureCapabilityKey } from './vocabulary';
9
10
 
@@ -42,6 +43,17 @@ export type {
42
43
  /** Closed lifecycle states exposed by the feature host. */
43
44
  export type RenderFeatureStatus = 'active' | 'failed' | 'disabled' | 'disposed';
44
45
 
46
+ /**
47
+ * Graph placement for a producer-owned feature.
48
+ *
49
+ * `scene` is admitted after the opaque scene and before transmission,
50
+ * ordinary transparency, and volumetric composition. `post` is admitted at
51
+ * the existing post-TAA extension point. Keeping this as one closed value
52
+ * lets the Standard owner place atmospheric transport without adding a
53
+ * second renderer or a feature-specific side channel.
54
+ */
55
+ export type RenderFeaturePlacement = 'scene' | 'post';
56
+
45
57
  /**
46
58
  * Shader preparation policy for feature-owned GPU programs.
47
59
  *
@@ -63,6 +75,27 @@ export interface RenderFeatureWorldVisibilitySnapshot {
63
75
  readonly snapshot: VisibilitySnapshot;
64
76
  }
65
77
 
78
+ /** Renderer-owned view facts shared by feature extraction and temporal owners. */
79
+ export interface RenderFeatureViewContext {
80
+ readonly identity: string;
81
+ readonly width: number;
82
+ readonly height: number;
83
+ readonly cameraRevision: number;
84
+ readonly deviceGeneration: number;
85
+ readonly cameraPosition: readonly [number, number, number];
86
+ /** Stable world anchor for light-space cloud coverage (never screen-space). */
87
+ readonly shadowAnchor?: readonly [number, number, number];
88
+ readonly cameraCut?: boolean;
89
+ readonly recovery?: boolean;
90
+ readonly sceneDepthVersion?: number;
91
+ }
92
+
93
+ /** Normal frame projection consumed by feature owners at extract time. */
94
+ export interface RenderFeatureFrameContext {
95
+ readonly cloudLayer?: import('../cloud/extract').ExtractedCloudLayer;
96
+ readonly view?: RenderFeatureViewContext;
97
+ }
98
+
66
99
  /** A producer's structured report for one hidden render candidate. */
67
100
  export interface RenderFeatureHiddenEntityReport {
68
101
  readonly world: World;
@@ -73,6 +106,16 @@ export interface RenderFeatureExtractContext {
73
106
  readonly worlds: readonly World[];
74
107
  readonly owner: number;
75
108
  readonly frameNumber: number;
109
+ /**
110
+ * Renderer-selected display camera for this frame. Features that affect the
111
+ * display must derive their active plan from this snapshot instead of
112
+ * scanning every Camera in the composed worlds.
113
+ */
114
+ readonly selectedCamera?: CameraSnapshot;
115
+ /** Renderer capability facts for source extraction and inspect projections. */
116
+ readonly caps?: Readonly<RhiCaps>;
117
+ /** Normal frame-owner projection; feature code must consume this snapshot. */
118
+ readonly frame?: RenderFeatureFrameContext;
76
119
  /** Same-batch World snapshots; absent for synthetic direct feature probes. */
77
120
  readonly visibilitySnapshots?: readonly RenderFeatureWorldVisibilitySnapshot[];
78
121
  /** Host-owned report sink; feature code never owns the merged diagnostic. */
@@ -106,6 +149,8 @@ export interface RenderFeatureSubmission {
106
149
  */
107
150
  export interface RenderFeature<FrameData> {
108
151
  readonly identity: string;
152
+ /** Optional graph placement; omitted features retain the historical post stage. */
153
+ readonly placement?: RenderFeaturePlacement;
109
154
  readonly requiredCapabilities?: readonly RenderFeatureCapabilityKey[];
110
155
  /** Optional feature-owned shader preparation policy; defaults to `validated`. */
111
156
  readonly shaderModuleMode?: RenderFeatureShaderModuleMode;
@@ -126,6 +171,8 @@ export interface RenderFeature<FrameData> {
126
171
  readonly source: string;
127
172
  }[];
128
173
  extract(context: RenderFeatureExtractContext): Result<FrameData, RenderError>;
174
+ /** GUID roots needed by the declarative plan; the publisher carries their asset closure. */
175
+ assetDependencies?(data: FrameData): readonly string[];
129
176
  plan(data: FrameData, context: RenderFeaturePlanContext): Result<RenderFeaturePlan, RenderError>;
130
177
  /**
131
178
  * Consume frame-owned producer state only after the compiled graph reached
@@ -133,6 +180,8 @@ export interface RenderFeature<FrameData> {
133
180
  * extracted frame and never during declarative planning.
134
181
  */
135
182
  onFrameSubmitted?(data: FrameData, submission?: RenderFeatureSubmission): void;
183
+ /** Consume source-owned intents after submission; feedback must be structured-cloneable. */
184
+ onSourceFrameSubmitted?(data: FrameData, feedback: unknown): void;
136
185
  /**
137
186
  * Discard frame-owned producer state when graph admission or submission is
138
187
  * rejected. This is the symmetric recovery path for onFrameSubmitted.
@@ -151,4 +200,6 @@ export interface RenderFeatureDiagnostics {
151
200
  readonly order: number;
152
201
  readonly status: RenderFeatureStatus;
153
202
  readonly latestError: RenderFeatureErrorDescriptor | undefined;
203
+ /** Optional producer-owned detached inspection snapshot from the latest extract. */
204
+ readonly inspection?: unknown;
154
205
  }