@forgeax/engine-render 0.1.33 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (518) hide show
  1. package/README.md +1010 -124
  2. package/dist/assembly/backend-contract.d.ts +2 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  5. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  6. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  7. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  8. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  9. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  10. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  11. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  12. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  14. package/dist/assembly/factory.d.ts +1 -1
  15. package/dist/assembly/factory.d.ts.map +1 -1
  16. package/dist/assembly/host-contract.d.ts +3 -3
  17. package/dist/assembly/host-contract.d.ts.map +1 -1
  18. package/dist/assembly/material/assembly.d.ts.map +1 -1
  19. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  20. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  21. package/dist/assembly/material-shader-policy.d.ts +16 -2
  22. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  23. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  24. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  25. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  26. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  27. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  28. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  29. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  30. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  31. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  32. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  33. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  34. package/dist/assembly/renderer-inspection.d.ts +11 -0
  35. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  36. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  37. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  38. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  39. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  40. package/dist/assembly/webgpu-ready.d.ts +1 -1
  41. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  42. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  43. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  44. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  45. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  46. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  47. package/dist/authoring.mjs +1 -1
  48. package/dist/barrel-distortion.d.ts +47 -0
  49. package/dist/barrel-distortion.d.ts.map +1 -0
  50. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  51. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  52. package/dist/{chunk-ZDQWGQW7.mjs → chunk-HEB564WF.mjs} +4 -4
  53. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-HEB564WF.mjs.map} +1 -1
  54. package/dist/{chunk-VOZWDM3L.mjs → chunk-MKDIT2EM.mjs} +1307 -188
  55. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  56. package/dist/{chunk-LEAXOMYJ.mjs → chunk-OCDLEI6I.mjs} +3 -3
  57. package/dist/{chunk-LEAXOMYJ.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  58. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  59. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  60. package/dist/{chunk-3RTCJTH4.mjs → chunk-SHFUFJ5N.mjs} +184 -13
  61. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  62. package/dist/{chunk-OO3DRYK7.mjs → chunk-UI5SFODX.mjs} +176 -96
  63. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  64. package/dist/{chunk-PLAXOOX5.mjs → chunk-UINHLCZA.mjs} +561 -79
  65. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  66. package/dist/{chunk-NB2S7ZRX.mjs → chunk-WEX45HKH.mjs} +127 -386
  67. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  68. package/dist/cloud/density.d.ts +55 -0
  69. package/dist/cloud/density.d.ts.map +1 -0
  70. package/dist/cloud/extract.d.ts +25 -0
  71. package/dist/cloud/extract.d.ts.map +1 -0
  72. package/dist/cloud/feature.d.ts +57 -0
  73. package/dist/cloud/feature.d.ts.map +1 -0
  74. package/dist/cloud/frame-context.d.ts +8 -0
  75. package/dist/cloud/frame-context.d.ts.map +1 -0
  76. package/dist/cloud/inspection.d.ts +59 -0
  77. package/dist/cloud/inspection.d.ts.map +1 -0
  78. package/dist/cloud/optics.d.ts +56 -0
  79. package/dist/cloud/optics.d.ts.map +1 -0
  80. package/dist/cloud/parameters.d.ts +73 -0
  81. package/dist/cloud/parameters.d.ts.map +1 -0
  82. package/dist/cloud/resources.d.ts +60 -0
  83. package/dist/cloud/resources.d.ts.map +1 -0
  84. package/dist/cloud/shadow.d.ts +42 -0
  85. package/dist/cloud/shadow.d.ts.map +1 -0
  86. package/dist/cloud/temporal.d.ts +74 -0
  87. package/dist/cloud/temporal.d.ts.map +1 -0
  88. package/dist/components/barrel-distortion.d.ts +13 -0
  89. package/dist/components/barrel-distortion.d.ts.map +1 -0
  90. package/dist/components/cloud-layer.d.ts +29 -0
  91. package/dist/components/cloud-layer.d.ts.map +1 -0
  92. package/dist/components/index.d.ts +2 -0
  93. package/dist/components/index.d.ts.map +1 -1
  94. package/dist/components/instances.d.ts +20 -6
  95. package/dist/components/instances.d.ts.map +1 -1
  96. package/dist/construct-renderer.d.ts +1 -1
  97. package/dist/construct-renderer.d.ts.map +1 -1
  98. package/dist/construct-renderer.mjs +6759 -2875
  99. package/dist/construct-renderer.mjs.map +1 -1
  100. package/dist/dynamic-geometry.d.ts +5 -1
  101. package/dist/dynamic-geometry.d.ts.map +1 -1
  102. package/dist/errors/cloud.d.ts +59 -0
  103. package/dist/errors/cloud.d.ts.map +1 -0
  104. package/dist/errors/render.d.ts +18 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  107. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  108. package/dist/extract/camera.d.ts.map +1 -1
  109. package/dist/extract/contracts.d.ts +5 -1
  110. package/dist/extract/contracts.d.ts.map +1 -1
  111. package/dist/features/barrel-distortion.d.ts +29 -0
  112. package/dist/features/barrel-distortion.d.ts.map +1 -0
  113. package/dist/features/error-reporting.d.ts +6 -2
  114. package/dist/features/error-reporting.d.ts.map +1 -1
  115. package/dist/features/host.d.ts +10 -0
  116. package/dist/features/host.d.ts.map +1 -1
  117. package/dist/features/plan.d.ts +8 -0
  118. package/dist/features/plan.d.ts.map +1 -1
  119. package/dist/features/render-graph-contribution.d.ts +5 -0
  120. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  121. package/dist/features/render-graph-raster.d.ts +1 -0
  122. package/dist/features/render-graph-raster.d.ts.map +1 -1
  123. package/dist/features/targets.d.ts +2 -0
  124. package/dist/features/targets.d.ts.map +1 -1
  125. package/dist/features/types.d.ts +44 -0
  126. package/dist/features/types.d.ts.map +1 -1
  127. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  128. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  129. package/dist/gpu-dirty-ranges.d.ts +11 -0
  130. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  131. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  132. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  133. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  134. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  135. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  136. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  137. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  138. package/dist/gpu-driven/production-raster.d.ts +47 -3
  139. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  140. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  141. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  142. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  143. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  144. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  145. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  146. package/dist/gpu-scene.d.ts +5 -0
  147. package/dist/gpu-scene.d.ts.map +1 -1
  148. package/dist/hdrp-buffers.d.ts +2 -2
  149. package/dist/hdrp-buffers.d.ts.map +1 -1
  150. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +27 -7
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +258 -8
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +135 -1
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instance-buffer-cache.d.ts +4 -4
  159. package/dist/instance-buffer-cache.d.ts.map +1 -1
  160. package/dist/instances.d.ts +48 -100
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.mjs +7 -7
  163. package/dist/pbr-pipeline.d.ts +19 -1
  164. package/dist/pbr-pipeline.d.ts.map +1 -1
  165. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  166. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  167. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  168. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  169. package/dist/pipeline/standard-output/types.d.ts +4 -2
  170. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  171. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  172. package/dist/pipeline/standard-post.d.ts.map +1 -1
  173. package/dist/pipeline-builder.d.ts +1 -1
  174. package/dist/pipeline-builder.d.ts.map +1 -1
  175. package/dist/plugin.d.ts.map +1 -1
  176. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  177. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  178. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  179. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  180. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  181. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  182. package/dist/record/fold-buckets.d.ts +95 -0
  183. package/dist/record/fold-buckets.d.ts.map +1 -0
  184. package/dist/record/fold-instance-buffer.d.ts +6 -0
  185. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  186. package/dist/record/frame-lighting.d.ts +1 -0
  187. package/dist/record/frame-lighting.d.ts.map +1 -1
  188. package/dist/record/frame-snapshot.d.ts +37 -3
  189. package/dist/record/frame-snapshot.d.ts.map +1 -1
  190. package/dist/record/frame.d.ts +10 -61
  191. package/dist/record/frame.d.ts.map +1 -1
  192. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  193. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  194. package/dist/record/gpu-timing.d.ts +8 -0
  195. package/dist/record/gpu-timing.d.ts.map +1 -1
  196. package/dist/record/main-pass-geometry.d.ts +21 -5
  197. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  198. package/dist/record/main-pass-material.d.ts +7 -1
  199. package/dist/record/main-pass-material.d.ts.map +1 -1
  200. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  201. package/dist/record/main-pass.d.ts +13 -2
  202. package/dist/record/main-pass.d.ts.map +1 -1
  203. package/dist/record/motion-blur-receipt.d.ts +11 -0
  204. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  205. package/dist/record/probe-blend-buffer.d.ts +16 -0
  206. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  207. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  208. package/dist/record/render-context.d.ts +22 -3
  209. package/dist/record/render-context.d.ts.map +1 -1
  210. package/dist/record/shadow-pass.d.ts +2 -0
  211. package/dist/record/shadow-pass.d.ts.map +1 -1
  212. package/dist/record/skybox-post-pass.d.ts +1 -1
  213. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  214. package/dist/record/typed-frame-graph.d.ts +22 -2
  215. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  216. package/dist/record/view-ubo.d.ts +11 -3
  217. package/dist/record/view-ubo.d.ts.map +1 -1
  218. package/dist/record/volume-params.d.ts +9 -0
  219. package/dist/record/volume-params.d.ts.map +1 -0
  220. package/dist/recovery/render-system-candidate.d.ts +10 -0
  221. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  222. package/dist/reflection/record-owner.d.ts.map +1 -1
  223. package/dist/render-contract.d.ts +42 -4
  224. package/dist/render-contract.d.ts.map +1 -1
  225. package/dist/render-graph-primitives.d.ts.map +1 -1
  226. package/dist/render-pipeline.d.ts +103 -2
  227. package/dist/render-pipeline.d.ts.map +1 -1
  228. package/dist/render-system-extract-tail.d.ts +3 -2
  229. package/dist/render-system-extract-tail.d.ts.map +1 -1
  230. package/dist/render-system-extract.d.ts +16 -9
  231. package/dist/render-system-extract.d.ts.map +1 -1
  232. package/dist/render-system-presentation.d.ts +23 -0
  233. package/dist/render-system-presentation.d.ts.map +1 -0
  234. package/dist/render-system-producer-roots.d.ts +10 -0
  235. package/dist/render-system-producer-roots.d.ts.map +1 -0
  236. package/dist/render-system-residency.d.ts +12 -0
  237. package/dist/render-system-residency.d.ts.map +1 -0
  238. package/dist/render-system.d.ts +19 -14
  239. package/dist/render-system.d.ts.map +1 -1
  240. package/dist/scene/probe-blend.d.ts +27 -0
  241. package/dist/scene/probe-blend.d.ts.map +1 -1
  242. package/dist/scene/render-scene.d.ts +12 -5
  243. package/dist/scene/render-scene.d.ts.map +1 -1
  244. package/dist/ssao-buffers.d.ts +9 -0
  245. package/dist/ssao-buffers.d.ts.map +1 -1
  246. package/dist/surface/dynamic-input.d.ts +133 -0
  247. package/dist/surface/dynamic-input.d.ts.map +1 -0
  248. package/dist/surface/gpu-driven.d.ts +41 -0
  249. package/dist/surface/gpu-driven.d.ts.map +1 -0
  250. package/dist/surface/submission-observation.d.ts +136 -0
  251. package/dist/surface/submission-observation.d.ts.map +1 -0
  252. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  253. package/dist/temporal/gpu.d.ts +13 -1
  254. package/dist/temporal/gpu.d.ts.map +1 -1
  255. package/dist/temporal/index.mjs +5 -5
  256. package/dist/temporal/inspection.d.ts.map +1 -1
  257. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  258. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  259. package/dist/transmission/single-layer-medium.d.ts +89 -0
  260. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  261. package/dist/typed-render-graph-primitives.d.ts +14 -2
  262. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  263. package/dist/volume/component.d.ts +9 -4
  264. package/dist/volume/component.d.ts.map +1 -1
  265. package/dist/volume/extract.d.ts +1 -1
  266. package/dist/volume/extract.d.ts.map +1 -1
  267. package/dist/volume/inspection.d.ts +2 -0
  268. package/dist/volume/inspection.d.ts.map +1 -1
  269. package/dist/volume/passes.d.ts +4 -1
  270. package/dist/volume/passes.d.ts.map +1 -1
  271. package/dist/volume/resources.d.ts.map +1 -1
  272. package/package.json +22 -21
  273. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  274. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  275. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  276. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  277. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  278. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  279. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  280. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  281. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  282. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  283. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  284. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  285. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  286. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  287. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  288. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  289. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  290. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  291. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  292. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  293. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  294. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  295. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  296. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  297. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  298. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  299. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  300. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  301. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  302. package/src/__tests__/instances-store.unit.test.ts +97 -305
  303. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  304. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  305. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  306. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  307. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  308. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  309. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  310. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  311. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  312. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  313. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  314. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  315. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  316. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  317. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  318. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  319. package/src/__tests__/render-error-code-owner.test-d.ts +7 -0
  320. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  321. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  322. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  323. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  324. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  325. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  326. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  327. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  328. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  329. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  330. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  331. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  332. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  333. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  334. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  335. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  336. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  337. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  338. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  339. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  340. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  341. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  342. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  343. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  344. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  345. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  346. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  347. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  348. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  349. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  350. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  351. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  352. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  353. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  354. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  355. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  356. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  357. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  358. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  359. package/src/assembly/backend-contract.ts +30 -0
  360. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  361. package/src/assembly/canvas-draw-guard.ts +11 -0
  362. package/src/assembly/cloud-shadow-entry.ts +22 -0
  363. package/src/assembly/dynamic-geometry-host.ts +65 -37
  364. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  365. package/src/assembly/factory.ts +2 -30
  366. package/src/assembly/host-contract.ts +3 -3
  367. package/src/assembly/material/assembly.ts +25 -13
  368. package/src/assembly/material/pipeline-helpers.ts +53 -12
  369. package/src/assembly/material-shader-policy.ts +55 -0
  370. package/src/assembly/material-shader-prewarm.ts +21 -10
  371. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  372. package/src/assembly/recovery/renderer-recover.ts +41 -18
  373. package/src/assembly/render-feature-post-processes.ts +54 -0
  374. package/src/assembly/renderer-facade.ts +4 -1
  375. package/src/assembly/renderer-feature-inspection.ts +8 -2
  376. package/src/assembly/renderer-frame-transaction.ts +23 -0
  377. package/src/assembly/renderer-inspection.ts +28 -0
  378. package/src/assembly/skin-palette-owner.ts +1 -1
  379. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  380. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  381. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  382. package/src/assembly/webgpu-ready.ts +115 -61
  383. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  384. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  385. package/src/assembly/webgpu-renderer.ts +214 -252
  386. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  387. package/src/barrel-distortion.ts +247 -0
  388. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  389. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  390. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  391. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  392. package/src/cloud/density.ts +600 -0
  393. package/src/cloud/extract.ts +110 -0
  394. package/src/cloud/feature.ts +1810 -0
  395. package/src/cloud/frame-context.ts +42 -0
  396. package/src/cloud/inspection.ts +130 -0
  397. package/src/cloud/optics.ts +285 -0
  398. package/src/cloud/parameters.ts +255 -0
  399. package/src/cloud/resources.ts +122 -0
  400. package/src/cloud/shadow.ts +167 -0
  401. package/src/cloud/temporal.ts +226 -0
  402. package/src/components/barrel-distortion.ts +46 -0
  403. package/src/components/cloud-layer.ts +47 -0
  404. package/src/components/index.ts +2 -0
  405. package/src/components/instances.ts +18 -45
  406. package/src/components/sprite-instances.ts +1 -1
  407. package/src/construct-renderer.ts +1 -1
  408. package/src/dynamic-geometry.ts +12 -1
  409. package/src/errors/cloud.ts +103 -0
  410. package/src/errors/render.ts +44 -7
  411. package/src/examples/single-layer-medium-surface.ts +59 -0
  412. package/src/extract/camera.ts +15 -1
  413. package/src/extract/contracts.ts +5 -0
  414. package/src/features/barrel-distortion.ts +172 -0
  415. package/src/features/error-reporting.ts +26 -6
  416. package/src/features/host.ts +115 -14
  417. package/src/features/plan.ts +8 -0
  418. package/src/features/render-graph-contribution.ts +9 -0
  419. package/src/features/render-graph-raster.ts +45 -3
  420. package/src/features/targets.ts +66 -0
  421. package/src/features/types.ts +47 -0
  422. package/src/fullscreen-post-process-pass.ts +41 -9
  423. package/src/gpu-dirty-ranges.ts +48 -0
  424. package/src/gpu-driven/batch-topology.ts +53 -0
  425. package/src/gpu-driven/material-artifacts.ts +33 -25
  426. package/src/gpu-driven/prepared-draw.ts +12 -4
  427. package/src/gpu-driven/production-raster-material.ts +1894 -0
  428. package/src/gpu-driven/production-raster.ts +825 -784
  429. package/src/gpu-driven/resource-allocation.ts +142 -0
  430. package/src/gpu-driven/shadow-ownership.ts +71 -0
  431. package/src/gpu-driven/view-gpu.ts +164 -10
  432. package/src/gpu-scene.ts +75 -84
  433. package/src/hdrp-buffers.ts +4 -3
  434. package/src/ibl/skylight-bind-group.ts +49 -7
  435. package/src/index.ts +196 -9
  436. package/src/inspection-types.ts +162 -0
  437. package/src/instance-buffer-cache.ts +4 -4
  438. package/src/instances.ts +149 -569
  439. package/src/pbr-pipeline.ts +219 -13
  440. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  441. package/src/pipeline/standard-forward-lane.ts +313 -57
  442. package/src/pipeline/standard-output/graph.ts +8 -2
  443. package/src/pipeline/standard-output/types.ts +12 -1
  444. package/src/pipeline/standard-pipeline.ts +291 -18
  445. package/src/pipeline/standard-post.ts +90 -24
  446. package/src/pipeline-builder.ts +1 -1
  447. package/src/plugin.ts +4 -0
  448. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  449. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  450. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  451. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  452. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  453. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  454. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  455. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  456. package/src/record/barrel-distortion-frame.ts +110 -0
  457. package/src/record/dynamic-geometry-consumption.ts +39 -9
  458. package/src/record/fold-buckets.ts +852 -0
  459. package/src/record/fold-instance-buffer.ts +51 -0
  460. package/src/record/frame-lighting.ts +36 -2
  461. package/src/record/frame-snapshot.ts +39 -3
  462. package/src/record/frame.ts +217 -1084
  463. package/src/record/gpu-draw-receipts.ts +38 -0
  464. package/src/record/gpu-timing.ts +48 -5
  465. package/src/record/main-pass-geometry.ts +251 -82
  466. package/src/record/main-pass-material.ts +66 -4
  467. package/src/record/main-pass-sprite-draws.ts +7 -65
  468. package/src/record/main-pass.ts +156 -20
  469. package/src/record/motion-blur-receipt.ts +91 -0
  470. package/src/record/probe-blend-buffer.ts +180 -0
  471. package/src/record/recovery-pipeline.ts +35 -3
  472. package/src/record/render-context.ts +39 -3
  473. package/src/record/shadow-pass.ts +30 -1
  474. package/src/record/skybox-post-pass.ts +28 -4
  475. package/src/record/typed-frame-graph.ts +770 -134
  476. package/src/record/view-ubo.ts +26 -3
  477. package/src/record/volume-params.ts +225 -0
  478. package/src/recovery/render-system-candidate.ts +235 -42
  479. package/src/reflection/record-owner.ts +7 -3
  480. package/src/render-contract.ts +48 -4
  481. package/src/render-graph-primitives.ts +7 -1
  482. package/src/render-pipeline.ts +130 -0
  483. package/src/render-system-extract-tail.ts +57 -61
  484. package/src/render-system-extract.ts +74 -76
  485. package/src/render-system-presentation.ts +56 -0
  486. package/src/render-system-producer-roots.ts +96 -0
  487. package/src/render-system-residency.ts +159 -0
  488. package/src/render-system.ts +347 -363
  489. package/src/scene/probe-blend.ts +96 -4
  490. package/src/scene/render-scene.ts +349 -280
  491. package/src/ssao-buffers.ts +95 -2
  492. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  493. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  494. package/src/surface/dynamic-input.ts +658 -0
  495. package/src/surface/gpu-driven.ts +147 -0
  496. package/src/surface/submission-observation.ts +517 -0
  497. package/src/systems/skin-palette-allocator.ts +4 -1
  498. package/src/temporal/gpu.ts +101 -17
  499. package/src/temporal/inspection.ts +7 -1
  500. package/src/temporal/standard-scene-data.ts +5 -0
  501. package/src/temporal/target-coverage-attachment.ts +4 -0
  502. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  503. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  504. package/src/transmission/single-layer-medium.ts +322 -0
  505. package/src/typed-render-graph-primitives.ts +70 -2
  506. package/src/volume/component.ts +10 -9
  507. package/src/volume/extract.ts +11 -5
  508. package/src/volume/inspection.ts +3 -0
  509. package/src/volume/passes.ts +87 -4
  510. package/src/volume/resources.ts +2 -1
  511. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  512. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  513. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  514. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  515. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  516. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  517. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  518. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -6,9 +6,16 @@ import {
6
6
  RenderGraphError,
7
7
  } from '@forgeax/engine-render-graph';
8
8
  import { err, ok, type Result } from '@forgeax/engine-types';
9
+ import { CLOUD_LAYER_FEATURE_IDENTITY } from '../cloud/feature';
9
10
  import { addAtmosphereBackground } from '../environment/background';
10
11
  import { SceneDataUnavailableError, StandardProfileInvalidError } from '../errors/render';
11
12
  import type { FramePlan } from '../extract/environment';
13
+ import { BARREL_DISTORTION_FEATURE_IDENTITY } from '../features/barrel-distortion';
14
+ import {
15
+ GPU_TEXTURE_USAGE_COPY_SRC,
16
+ GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
17
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING,
18
+ } from '../gpu-texture-usage';
12
19
  import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from '../gpu-usage';
13
20
  import { DEFERRED_COLOR_FORMATS } from '../pipeline-spec';
14
21
  import { VIEW_UNIFORM_BYTES } from '../record/view-ubo';
@@ -16,12 +23,14 @@ import type {
16
23
  RenderPipeline,
17
24
  RenderPipelineBuildContext,
18
25
  RenderPipelineFrame,
26
+ RenderPipelineSurfaceMediumPair,
19
27
  RenderPipelineTopology,
20
28
  } from '../render-pipeline';
21
29
  import {
22
30
  createRenderPipelineTarget,
23
31
  importRenderPipelineSurface,
24
32
  type RenderPipelineTarget,
33
+ renderPipelineCloudHistoryTargets,
25
34
  } from '../render-pipeline';
26
35
  import { addSsrCompositionPass } from '../ssr/compose';
27
36
  import { addSsrSpatialPasses } from '../ssr/graph';
@@ -48,6 +57,10 @@ import {
48
57
  import { addTypedShadowPasses } from '../typed-shadow-passes';
49
58
  import { addAuthoredVolumetricFogPasses } from '../volume/passes';
50
59
  import { renderExtentSize } from './render-extent';
60
+ import {
61
+ addSingleLayerMediumPasses,
62
+ addSingleLayerMediumRawDepthProducer,
63
+ } from './single-layer-medium-passes';
51
64
  import type { StandardPipelineBuildContext } from './standard-build-context';
52
65
  import { buildStandardForwardLane } from './standard-forward-lane';
53
66
  import {
@@ -172,6 +185,10 @@ function buildStandardDeferredLane(
172
185
  if (!surface.ok) return surface;
173
186
  const internalSize =
174
187
  topology.extent === undefined ? 'surface' : renderExtentSize(topology.extent, 'internal');
188
+ const internalCopySize =
189
+ topology.extent === undefined
190
+ ? { width: topology.surface.width, height: topology.surface.height }
191
+ : renderExtentSize(topology.extent, 'internal');
175
192
  const buffers = importStandardClusterBuffers(graph, lighting);
176
193
  if (!buffers.ok) return buffers;
177
194
  const membership =
@@ -217,6 +234,28 @@ function buildStandardDeferredLane(
217
234
  if (!gbuffer2.ok) return gbuffer2;
218
235
  const scene = target(graph, 'hdrp-scene-color', { format: 'rgba16float', size: internalSize });
219
236
  if (!scene.ok) return scene;
237
+ const mediumTargets =
238
+ topology.singleLayerMedium === true
239
+ ? (() => {
240
+ const nearestLayer = target(graph, 'single-layer-medium-nearest-layer', {
241
+ format: scene.value.format,
242
+ size: internalSize,
243
+ // The color pass samples this target with a `texture_2d`; keep
244
+ // it single-sample even when a future deferred path is MSAA.
245
+ sampleCount: 1,
246
+ domain: 'linear-ldr',
247
+ });
248
+ if (!nearestLayer.ok) return nearestLayer;
249
+ const nearestDepth = target(graph, 'single-layer-medium-nearest-depth', {
250
+ format: 'depth24plus-stencil8',
251
+ size: internalSize,
252
+ sampleCount: 1,
253
+ });
254
+ if (!nearestDepth.ok) return nearestDepth;
255
+ return ok({ nearestLayer: nearestLayer.value, nearestDepth: nearestDepth.value });
256
+ })()
257
+ : ok(undefined);
258
+ if (!mediumTargets.ok) return mediumTargets;
220
259
  const reflectionFallback =
221
260
  topology.reflectionFallback?.enabled === true || topology.ssr?.status === 'admitted'
222
261
  ? target(graph, 'reflection-fallback-linear-hdr', {
@@ -270,6 +309,11 @@ function buildStandardDeferredLane(
270
309
  colorTargets: [gbuffer0.value, gbuffer1.value, gbuffer2.value],
271
310
  depth: depth.value,
272
311
  selector: { LightMode: ['Deferred'] },
312
+ // The G-buffer only admits opaque Standard materials. Medium Surface
313
+ // programs have no Deferred entry and acquire raw depth in their later
314
+ // paired color pass; filtering here also avoids assembling their bind
315
+ // groups before that producer exists.
316
+ recordMode: 'opaque',
273
317
  passKind: 'deferred',
274
318
  clearColor: [0, 0, 0, 0],
275
319
  });
@@ -301,6 +345,85 @@ function buildStandardDeferredLane(
301
345
  if (!skybox.ok) return skybox;
302
346
  }
303
347
 
348
+ const featureRasterWork =
349
+ context.hasFeatureRasterWork?.(CLOUD_LAYER_FEATURE_IDENTITY, 'scene') === true;
350
+ const cloudScene = featureRasterWork
351
+ ? target(graph, 'cloud-layer-scene-color', {
352
+ format: scene.value.format,
353
+ size: internalSize,
354
+ sampleCount: 1,
355
+ domain: 'linear-hdr',
356
+ usage:
357
+ GPU_TEXTURE_USAGE_COPY_SRC |
358
+ GPU_TEXTURE_USAGE_RENDER_ATTACHMENT |
359
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING,
360
+ })
361
+ : ok(undefined);
362
+ if (!cloudScene.ok) return cloudScene;
363
+ const cloudShadow =
364
+ featureRasterWork && context.cloudShadowResolution !== undefined
365
+ ? target(graph, 'cloud-layer-shadow', {
366
+ format: 'rgba16float',
367
+ size: {
368
+ width: context.cloudShadowResolution,
369
+ height: context.cloudShadowResolution,
370
+ depthOrArrayLayers: 1,
371
+ },
372
+ sampleCount: 1,
373
+ domain: 'linear-hdr',
374
+ usage:
375
+ GPU_TEXTURE_USAGE_COPY_SRC |
376
+ GPU_TEXTURE_USAGE_RENDER_ATTACHMENT |
377
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING,
378
+ })
379
+ : ok(undefined);
380
+ if (!cloudShadow.ok) return cloudShadow;
381
+ const featureTargets = [
382
+ {
383
+ name: 'linear-hdr',
384
+ kind: 'scene-color',
385
+ texture: scene.value.texture,
386
+ view: scene.value.view,
387
+ format: scene.value.format,
388
+ sampleCount: 1,
389
+ },
390
+ {
391
+ kind: 'scene-depth',
392
+ texture: depth.value.texture,
393
+ view: depth.value.view,
394
+ format: depth.value.format,
395
+ sampleCount: 1,
396
+ },
397
+ ...(cloudShadow.value === undefined
398
+ ? []
399
+ : [
400
+ {
401
+ name: 'cloud-shadow',
402
+ kind: 'scene-color' as const,
403
+ texture: cloudShadow.value.texture,
404
+ view: cloudShadow.value.view,
405
+ format: cloudShadow.value.format,
406
+ sampleCount: 1 as const,
407
+ },
408
+ ]),
409
+ ...(context.cloudHistory === undefined
410
+ ? []
411
+ : renderPipelineCloudHistoryTargets(context.cloudHistory)),
412
+ ] as const;
413
+ // Cloud density and its spatial shadow must be produced before the opaque
414
+ // receiver pass. The composite is projected separately below, after the
415
+ // receiver has populated the scene target; declaration order is execution
416
+ // order for the typed graph.
417
+ const shadowFeatures = context.contributeFeatures(
418
+ featureTargets,
419
+ [],
420
+ cloudShadow.value === undefined ? {} : { 'cloud-shadow': cloudShadow.value },
421
+ [],
422
+ 'scene',
423
+ ['cloud-layer-density-cache', 'cloud-layer-shadow'],
424
+ );
425
+ if (!shadowFeatures.ok) return shadowFeatures;
426
+
304
427
  // The lighting lane is the deferred Standard receiver. It deliberately
305
428
  // selects Forward passes for the same material handles that wrote the
306
429
  // G-buffer. Membership must not select the Deferred program/entries: those
@@ -329,14 +452,18 @@ function buildStandardDeferredLane(
329
452
  ...(shadows.value.directional === undefined ? [] : [shadows.value.directional]),
330
453
  shadows.value.spot,
331
454
  ...(shadows.value.point === undefined ? [] : [shadows.value.point]),
455
+ ...(cloudShadow.value === undefined ? [] : [cloudShadow.value]),
332
456
  ...(ssao === undefined ? [] : [ssao]),
333
457
  ],
334
458
  ...(shadows.value.directional === undefined
335
459
  ? {}
336
460
  : { directionalShadow: shadows.value.directional }),
337
461
  spotShadow: shadows.value.spot,
462
+ cloudShadow: cloudShadow.value,
338
463
  ...(ssao === undefined ? {} : { ssao }),
339
464
  ...(gpuDriven.value === undefined ? {} : { gpuDriven: gpuDriven.value }),
465
+ ...(gpuDriven.value === undefined ? {} : { gpuDrivenFilter: 'deferred-opaque' as const }),
466
+ ...(topology.singleLayerMedium === true ? { recordMode: 'opaque' as const } : {}),
340
467
  passKind: 'forward',
341
468
  extraAccesses: buffers.value === null ? [] : standardClusterReadAccesses(buffers.value),
342
469
  });
@@ -359,7 +486,7 @@ function buildStandardDeferredLane(
359
486
  if (!coverage.ok) return coverage;
360
487
  }
361
488
 
362
- const sceneOutput: RenderPipelineTarget = scene.value;
489
+ let sceneOutput: RenderPipelineTarget = scene.value;
363
490
  let secondaryReactivity: GraphTextureView | undefined;
364
491
  if (topology.ssr !== undefined) {
365
492
  const ssrView =
@@ -420,10 +547,18 @@ function buildStandardDeferredLane(
420
547
  }
421
548
 
422
549
  const transmissionDemand = transmissionDemandForTopology(topology);
550
+ const backdropDemand = {
551
+ activeCount: transmissionDemand.activeCount + (topology.singleLayerMedium === true ? 1 : 0),
552
+ needsRoughMips: transmissionDemand.needsRoughMips,
553
+ };
423
554
  const transmissionActive = resolveTransmissionBackdropTopology({
424
555
  demand: transmissionDemand,
425
556
  sourceSampleCount: scene.value.sampleCount,
426
557
  }).active;
558
+ const backdropActive = resolveTransmissionBackdropTopology({
559
+ demand: backdropDemand,
560
+ sourceSampleCount: scene.value.sampleCount,
561
+ }).active;
427
562
  const forwardExtraAccesses: GraphAccess[] =
428
563
  buffers.value === null ? [] : [...standardClusterReadAccesses(buffers.value)];
429
564
 
@@ -442,35 +577,158 @@ function buildStandardDeferredLane(
442
577
  ...(shadows.value.directional === undefined ? [] : [shadows.value.directional]),
443
578
  shadows.value.spot,
444
579
  ...(shadows.value.point === undefined ? [] : [shadows.value.point]),
580
+ ...(cloudShadow.value === undefined ? [] : [cloudShadow.value]),
445
581
  ...(ssao === undefined ? [] : [ssao]),
446
582
  ],
447
583
  ...(shadows.value.directional === undefined
448
584
  ? {}
449
585
  : { directionalShadow: shadows.value.directional }),
450
586
  spotShadow: shadows.value.spot,
587
+ cloudShadow: cloudShadow.value,
451
588
  ...(ssao === undefined ? {} : { ssao }),
452
589
  ...(gpuDriven.value === undefined ? {} : { gpuDriven: gpuDriven.value }),
453
590
  passKind: 'forward',
454
591
  excludeSelector: { LightMode: ['Deferred'] },
455
- ...(transmissionActive ? { recordMode: 'opaque' as const } : {}),
592
+ // Keep the deferred opaque lane separate from Surface medium passes.
593
+ recordMode: 'opaque' as const,
594
+ ...(gpuDriven.value === undefined ? {} : { gpuDrivenFilter: 'forward-only-opaque' as const }),
456
595
  ...(context.occlusion === undefined ? {} : { occlusion: context.occlusion }),
457
596
  extraAccesses: forwardExtraAccesses,
458
597
  });
459
598
  if (!forward.ok) return forward;
460
599
 
600
+ if (cloudScene.value !== undefined) {
601
+ const compositeFeatures = context.contributeFeatures(
602
+ featureTargets,
603
+ [],
604
+ {
605
+ 'motion-input': scene.value,
606
+ 'motion-output': cloudScene.value,
607
+ ...(cloudShadow.value === undefined ? {} : { 'cloud-shadow': cloudShadow.value }),
608
+ ...(context.cloudHistory === undefined
609
+ ? {}
610
+ : {
611
+ 'cloud-history-radiance-current': context.cloudHistory.currentRadiance,
612
+ 'cloud-history-radiance-previous': context.cloudHistory.previousRadiance,
613
+ 'cloud-history-transmittance-current': context.cloudHistory.currentTransmittance,
614
+ 'cloud-history-transmittance-previous': context.cloudHistory.previousTransmittance,
615
+ 'cloud-history-depth-current': context.cloudHistory.currentDepth,
616
+ 'cloud-history-depth-previous': context.cloudHistory.previousDepth,
617
+ }),
618
+ },
619
+ forwardExtraAccesses,
620
+ 'scene',
621
+ // One half-resolution transport MRT produces radiance, transmittance and
622
+ // representative depth; the full-resolution resolve consumes that same
623
+ // frame and advances the ping-pong history on submit.
624
+ ['cloud-layer-transport', 'cloud-layer-resolve'],
625
+ );
626
+ if (!compositeFeatures.ok) return compositeFeatures;
627
+ }
628
+
629
+ if (cloudScene.value !== undefined) sceneOutput = cloudScene.value;
630
+
461
631
  const transmission = addTransmissionBackdropPasses({
462
632
  graph,
463
633
  source: sceneOutput,
464
- demand: transmissionDemand,
465
- copySize: { width: topology.surface.width, height: topology.surface.height },
634
+ demand: backdropDemand,
635
+ copySize: internalCopySize,
466
636
  encodeRoughMip: context.encodeTransmissionMip,
467
637
  includeConsumerPasses: false,
468
638
  });
469
639
  if (!transmission.ok) return transmission;
470
- if (transmission.value.topology.active) {
471
- const transmissionPass = addTypedScenePass(graph, {
640
+ if (topology.singleLayerMedium === true) {
641
+ const nearestTargets = mediumTargets.value;
642
+ const backdrop = transmission.value.backdrop?.view;
643
+ if (nearestTargets === undefined || backdrop === undefined) {
644
+ return err(
645
+ new RenderGraphError({
646
+ code: 'resource-descriptor-invalid',
647
+ expected: 'single-layer medium graph has nearest targets and an opaque backdrop',
648
+ hint: 'keep the shared transmission backdrop copy ahead of the Surface passes',
649
+ detail: {
650
+ resourceLabel: 'single-layer-medium',
651
+ field: 'backdrop',
652
+ expected: 'resolved graph texture view',
653
+ actual: 'missing',
654
+ },
655
+ }),
656
+ );
657
+ }
658
+ const rawDepth = addSingleLayerMediumRawDepthProducer({
659
+ graph,
660
+ sourceColor: sceneOutput,
661
+ sourceDepth: depth.value,
662
+ size: internalSize,
663
+ });
664
+ if (!rawDepth.ok) return rawDepth;
665
+ // Standard owns this producer fact. Deferred depth is single-sample, so
666
+ // the independent r32float copy is available to both medium passes.
667
+ const surfacePair: RenderPipelineSurfaceMediumPair = {
668
+ opaqueColor: backdrop,
669
+ rawDepth: { status: 'available', view: rawDepth.value.view },
670
+ };
671
+ const mediumPasses = addSingleLayerMediumPasses({
672
+ graph,
673
+ size: internalSize,
674
+ ...nearestTargets,
675
+ color: sceneOutput,
676
+ depth: depth.value,
677
+ sampled: [
678
+ gbuffer0.value,
679
+ gbuffer1.value,
680
+ gbuffer2.value,
681
+ ...(shadows.value.directional === undefined ? [] : [shadows.value.directional]),
682
+ shadows.value.spot,
683
+ ...(shadows.value.point === undefined ? [] : [shadows.value.point]),
684
+ ...(cloudShadow.value === undefined ? [] : [cloudShadow.value]),
685
+ ...(ssao === undefined ? [] : [ssao]),
686
+ ],
687
+ directionalShadow: shadows.value.directional,
688
+ spotShadow: shadows.value.spot,
689
+ cloudShadow: cloudShadow.value,
690
+ ssao,
691
+ extraAccesses: forwardExtraAccesses,
692
+ surfacePair,
693
+ ...(gpuDriven.value === undefined ? {} : { gpuDriven: gpuDriven.value }),
694
+ });
695
+ if (!mediumPasses.ok) return mediumPasses;
696
+ }
697
+ if (backdropActive) {
698
+ if (transmissionActive) {
699
+ const transmissionPass = addTypedScenePass(graph, {
700
+ environment: atmosphere.value,
701
+ name: 'transmission-forward',
702
+ color: sceneOutput,
703
+ depth: depth.value,
704
+ selector: { LightMode: ['Forward'] },
705
+ colorLoadOp: 'load',
706
+ depthLoadOp: 'load',
707
+ sampled: [
708
+ gbuffer0.value,
709
+ gbuffer1.value,
710
+ gbuffer2.value,
711
+ ...(shadows.value.directional === undefined ? [] : [shadows.value.directional]),
712
+ shadows.value.spot,
713
+ ...(shadows.value.point === undefined ? [] : [shadows.value.point]),
714
+ ...(ssao === undefined ? [] : [ssao]),
715
+ ],
716
+ directionalShadow: shadows.value.directional,
717
+ spotShadow: shadows.value.spot,
718
+ ...(ssao === undefined ? {} : { ssao }),
719
+ passKind: 'forward',
720
+ recordMode: 'transmission',
721
+ // Inject the complete backdrop view so the Standard shader can select
722
+ // the producer's optional roughness mip level. mipViews[0] is only the
723
+ // copy destination view and intentionally exposes one level.
724
+ transmissionBackdrop: transmission.value.backdrop?.view,
725
+ extraAccesses: forwardExtraAccesses,
726
+ });
727
+ if (!transmissionPass.ok) return transmissionPass;
728
+ }
729
+ const transparentPass = addTypedScenePass(graph, {
472
730
  environment: atmosphere.value,
473
- name: 'transmission-forward',
731
+ name: 'transparent',
474
732
  color: sceneOutput,
475
733
  depth: depth.value,
476
734
  selector: { LightMode: ['Forward'] },
@@ -483,21 +741,25 @@ function buildStandardDeferredLane(
483
741
  ...(shadows.value.directional === undefined ? [] : [shadows.value.directional]),
484
742
  shadows.value.spot,
485
743
  ...(shadows.value.point === undefined ? [] : [shadows.value.point]),
744
+ ...(cloudShadow.value === undefined ? [] : [cloudShadow.value]),
486
745
  ...(ssao === undefined ? [] : [ssao]),
487
746
  ],
488
747
  directionalShadow: shadows.value.directional,
489
748
  spotShadow: shadows.value.spot,
749
+ cloudShadow: cloudShadow.value,
490
750
  ...(ssao === undefined ? {} : { ssao }),
491
751
  passKind: 'forward',
492
- recordMode: 'transmission',
493
- // Inject the complete backdrop view so the Standard shader can select
494
- // the producer's optional roughness mip level. mipViews[0] is only the
495
- // copy destination view and intentionally exposes one level.
496
- transmissionBackdrop: transmission.value.backdrop?.view,
752
+ recordMode: 'transparent',
753
+ transparentDepthWrite: true,
497
754
  extraAccesses: forwardExtraAccesses,
498
755
  });
499
- if (!transmissionPass.ok) return transmissionPass;
500
-
756
+ if (!transparentPass.ok) return transparentPass;
757
+ }
758
+ if (backdropActive) {
759
+ const temporal = addTransmissionBackdropTemporalPass(graph, sceneOutput);
760
+ if (!temporal.ok) return temporal;
761
+ }
762
+ if (!transmission.value.topology.active) {
501
763
  const transparentPass = addTypedScenePass(graph, {
502
764
  environment: atmosphere.value,
503
765
  name: 'transparent',
@@ -513,18 +775,19 @@ function buildStandardDeferredLane(
513
775
  ...(shadows.value.directional === undefined ? [] : [shadows.value.directional]),
514
776
  shadows.value.spot,
515
777
  ...(shadows.value.point === undefined ? [] : [shadows.value.point]),
778
+ ...(cloudShadow.value === undefined ? [] : [cloudShadow.value]),
516
779
  ...(ssao === undefined ? [] : [ssao]),
517
780
  ],
518
781
  directionalShadow: shadows.value.directional,
519
782
  spotShadow: shadows.value.spot,
783
+ cloudShadow: cloudShadow.value,
520
784
  ...(ssao === undefined ? {} : { ssao }),
521
785
  passKind: 'forward',
522
786
  recordMode: 'transparent',
787
+ transparentDepthWrite: true,
523
788
  extraAccesses: forwardExtraAccesses,
524
789
  });
525
790
  if (!transparentPass.ok) return transparentPass;
526
- const temporal = addTransmissionBackdropTemporalPass(graph, sceneOutput);
527
- if (!temporal.ok) return temporal;
528
791
  }
529
792
  if (topology.volumetricFog?.enabled === true) {
530
793
  const depthSample = graph.view(depth.value.texture, {
@@ -541,11 +804,15 @@ function buildStandardDeferredLane(
541
804
  shadows.value.directional?.view,
542
805
  shadows.value.spot.view,
543
806
  buffers.value,
807
+ cloudShadow.value?.view,
544
808
  );
545
809
  if (!volume.ok) return volume;
546
810
  }
547
811
  // The volume-composite pass remains in linear HDR before tone mapping.
548
812
 
813
+ // Generic post features consume the final deferred scene target after cloud
814
+ // and volume producers. Keep the same clustered, shadow, and SSAO reads that
815
+ // the Standard receiver exposes to feature-owned lighting passes.
549
816
  const features = context.contributeFeatures(
550
817
  [
551
818
  {
@@ -561,18 +828,24 @@ function buildStandardDeferredLane(
561
828
  texture: depth.value.texture,
562
829
  view: depth.value.view,
563
830
  format: depth.value.format,
564
- sampleCount: 1,
831
+ sampleCount: depth.value.sampleCount,
565
832
  },
566
833
  ],
567
834
  [],
568
835
  {},
569
836
  [
570
837
  ...forwardExtraAccesses,
571
- ...[shadows.value.directional, shadows.value.spot, shadows.value.point].flatMap((target) =>
838
+ ...[
839
+ shadows.value.directional,
840
+ shadows.value.spot,
841
+ shadows.value.point,
842
+ cloudShadow.value,
843
+ ].flatMap((target) =>
572
844
  target === undefined ? [] : [{ resource: target.view, usage: 'sampled-read' as const }],
573
845
  ),
574
846
  ...(ssao === undefined ? [] : [{ resource: ssao.view, usage: 'sampled-read' as const }]),
575
847
  ],
848
+ { exclude: [BARREL_DISTORTION_FEATURE_IDENTITY] },
576
849
  );
577
850
  if (!features.ok) return features;
578
851
  const observation = addTypedFrameObservationPass(graph, sceneOutput, 'forgeax::standard');
@@ -7,7 +7,11 @@ import { RenderGraphError } from '@forgeax/engine-render-graph';
7
7
  import { err, ok, type Result } from '@forgeax/engine-types';
8
8
  import { standardBloomAdmitted } from '../bloom-admission';
9
9
  import { addTypedDebugOverlayPass } from '../debug-draw-glue';
10
- import { SceneDataUnavailableError } from '../errors/render';
10
+ import { RenderFeatureCapabilityMissingError, SceneDataUnavailableError } from '../errors/render';
11
+ import {
12
+ BARREL_DISTORTION_FEATURE_IDENTITY,
13
+ BARREL_DISTORTION_POST_PROCESS_ID,
14
+ } from '../features/barrel-distortion';
11
15
  import { addDepthOfFieldPasses } from '../features/depth-of-field/depth-of-field-feature';
12
16
  import { addMotionBlurPass } from '../features/motion-blur/motion-blur-feature';
13
17
  import { GPU_TEXTURE_USAGE_COPY_SRC } from '../gpu-texture-usage';
@@ -392,9 +396,22 @@ export function addStandardPost(
392
396
  exposure: topology.output?.autoExposure === true,
393
397
  whiteBalance: topology.output?.whiteBalance === true,
394
398
  lut: topology.output?.colorLut === true,
399
+ barrelDistortion: topology.camera.barrelDistortion === true,
395
400
  fxaa: !clearOnly && topology.camera.antialias === 'fxaa',
396
401
  outputEncoding: 'explicit-oetf',
397
402
  });
403
+ if (
404
+ outputPlan.features.barrelDistortion &&
405
+ context.capabilities?.rgba16floatRenderable !== true
406
+ ) {
407
+ return err(
408
+ new RenderFeatureCapabilityMissingError(
409
+ BARREL_DISTORTION_FEATURE_IDENTITY,
410
+ 0,
411
+ 'rgba16floatRenderable',
412
+ ),
413
+ );
414
+ }
398
415
  const hdr =
399
416
  !clearOnly && (topology.camera.tonemap !== 'none' || topology.camera.antialias === 'taa');
400
417
  // Bloom is an HDR-domain effect and its recorders intentionally no-op when
@@ -410,7 +427,15 @@ export function addStandardPost(
410
427
  const rawOnly = !clearOnly && topology.surface.profile?.kind === 'raw-only';
411
428
  const outputDither = resolveOutputDither(topology.config);
412
429
  const motionBlur = !clearOnly && topology.temporal?.motionBlur === true;
413
- const postEffects = clearOnly ? [] : (topology.config?.postEffects ?? []);
430
+ // The barrel declaration is supplied by the ordinary feature host so its
431
+ // shader stays prepared and recoverable, but Standard owns its one explicit
432
+ // linear-LDR stage below. Do not send that identity through the generic
433
+ // encoded tail, or storage-buffer lanes would sample the image twice.
434
+ const postEffects = clearOnly
435
+ ? []
436
+ : (topology.config?.postEffects ?? []).filter(
437
+ (identity) => identity !== BARREL_DISTORTION_POST_PROCESS_ID,
438
+ );
414
439
  const rawOnlyPostInput =
415
440
  rawOnly && topology.lane.storageBuffer && postEffects.length > 0
416
441
  ? target(context, 'standard-post-effects-input', {
@@ -514,23 +539,23 @@ export function addStandardPost(
514
539
  // Feature projection and the built-in fallback share one target contract.
515
540
  // The projection runs after TAA so Motion Blur consumes the resolved color,
516
541
  // then both paths feed the same linear float target into Bloom/Output.
542
+ const featureTargets = [
543
+ {
544
+ kind: 'scene-color' as const,
545
+ texture: scene.texture,
546
+ view: scene.view,
547
+ format: scene.format,
548
+ sampleCount: scene.sampleCount,
549
+ },
550
+ {
551
+ kind: 'scene-depth' as const,
552
+ texture: depth.texture,
553
+ view: depth.view,
554
+ format: depth.format,
555
+ sampleCount: depth.sampleCount,
556
+ },
557
+ ];
517
558
  if (!clearOnly) {
518
- const featureTargets = [
519
- {
520
- kind: 'scene-color' as const,
521
- texture: scene.texture,
522
- view: scene.view,
523
- format: scene.format,
524
- sampleCount: scene.sampleCount,
525
- },
526
- {
527
- kind: 'scene-depth' as const,
528
- texture: depth.texture,
529
- view: depth.view,
530
- format: depth.format,
531
- sampleCount: depth.sampleCount,
532
- },
533
- ];
534
559
  if (motionBlur) {
535
560
  if (postTemporal === undefined) {
536
561
  return err(
@@ -543,10 +568,16 @@ export function addStandardPost(
543
568
  domain: hdr ? 'linear-hdr' : 'linear-ldr',
544
569
  });
545
570
  if (!blurred.ok) return blurred;
546
- const features = context.contributeFeatures(featureTargets, [postTemporal], {
547
- 'motion-input': postInput,
548
- 'motion-output': blurred.value,
549
- });
571
+ const features = context.contributeFeatures(
572
+ featureTargets,
573
+ [postTemporal],
574
+ {
575
+ 'motion-input': postInput,
576
+ 'motion-output': blurred.value,
577
+ },
578
+ [],
579
+ { exclude: [BARREL_DISTORTION_FEATURE_IDENTITY] },
580
+ );
550
581
  if (!features.ok) return features;
551
582
  if (context.hasFeature?.('forgeax.motion-blur') === true) {
552
583
  postInput = blurred.value;
@@ -559,6 +590,9 @@ export function addStandardPost(
559
590
  const features = context.contributeFeatures(
560
591
  featureTargets,
561
592
  sceneTemporal === undefined ? [] : [sceneTemporal],
593
+ {},
594
+ [],
595
+ { exclude: [BARREL_DISTORTION_FEATURE_IDENTITY] },
562
596
  );
563
597
  if (!features.ok) return features;
564
598
  }
@@ -638,6 +672,7 @@ export function addStandardPost(
638
672
  outputPlan.features.lut ||
639
673
  outputPlan.features.exposure ||
640
674
  outputPlan.features.whiteBalance ||
675
+ outputPlan.features.barrelDistortion ||
641
676
  // A receipt-bound observation request is an explicit producer demand, not
642
677
  // a new authored color feature. When a caller asks for the linear-LDR
643
678
  // domain on the ordinary ACES path, retain the same tone/output boundary
@@ -689,11 +724,42 @@ export function addStandardPost(
689
724
  postInput = lutOutput.value;
690
725
  }
691
726
 
692
- if (rawOnly) {
727
+ // Debug geometry is world-space scene content. Insert it before the spatial
728
+ // warp so its lines and markers bend with the rendered world. Screen-space
729
+ // diagnostics remain on the final surface below when no warp is active.
730
+ const debugOverlayBeforeBarrel = outputPlan.features.barrelDistortion;
731
+ if (rawOnly || debugOverlayBeforeBarrel) {
693
732
  const overlay = addTypedDebugOverlayPass(context.graph, postInput);
694
733
  if (!overlay.ok) return overlay;
695
734
  }
696
735
 
736
+ if (outputPlan.features.barrelDistortion) {
737
+ const barrelOutput = target(context, 'standard-barrel-distortion', {
738
+ format: 'rgba16float',
739
+ size: 'surface',
740
+ domain: 'linear-ldr',
741
+ });
742
+ if (!barrelOutput.ok) return barrelOutput;
743
+ const barrel = context.contributeFeatures(
744
+ featureTargets,
745
+ [],
746
+ { 'barrel-input': postInput, 'barrel-output': barrelOutput.value },
747
+ [],
748
+ { include: [BARREL_DISTORTION_FEATURE_IDENTITY] },
749
+ );
750
+ if (!barrel.ok) return barrel;
751
+ if (context.hasFeature?.(BARREL_DISTORTION_FEATURE_IDENTITY) !== true) {
752
+ return err(
753
+ new RenderFeatureCapabilityMissingError(
754
+ BARREL_DISTORTION_FEATURE_IDENTITY,
755
+ 0,
756
+ 'rgba16floatRenderable',
757
+ ),
758
+ );
759
+ }
760
+ postInput = barrelOutput.value;
761
+ }
762
+
697
763
  if (hdr || linearLdr || fxaa || rawOnly || motionBlur) {
698
764
  if (fxaa) {
699
765
  const output = splitOutput
@@ -797,7 +863,7 @@ export function addStandardPost(
797
863
  if (!effects.ok) return effects;
798
864
  }
799
865
 
800
- return rawOnly
866
+ return rawOnly || debugOverlayBeforeBarrel
801
867
  ? ok(undefined)
802
868
  : addTypedDebugOverlayPass(context.graph, surface.display ?? surface.storage);
803
869
  }
@@ -135,7 +135,7 @@ export interface PipelineBuilderContext {
135
135
  */
136
136
  readonly vertexBuffers: readonly GPUVertexBufferLayout[];
137
137
  /** Explicit layout family selected by the renderer assembly. */
138
- readonly layoutKind?: 'pbr-skin' | 'gpu-driven-skin' | undefined;
138
+ readonly layoutKind?: 'pbr-skin' | 'gpu-driven-skin' | 'gpu-driven-cluster-skin' | undefined;
139
139
  /** Pipeline label (for GPU debug captures); defaults to `pbr-pipeline-${id}`. */
140
140
  readonly label?: string | undefined;
141
141
  /**