@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
@@ -350,6 +350,51 @@ export function appendInjection(
350
350
  }
351
351
  }
352
352
 
353
+ /**
354
+ * Append the renderer-owned inputs required by the Engine single-layer
355
+ * medium template. They intentionally live after the normal IBL and
356
+ * transmission injections so authored parameter schemas remain the only
357
+ * source of the prefix. The raw-depth texture is an r32float producer
358
+ * resource and therefore uses the unfilterable-float/non-filtering pair.
359
+ */
360
+ export function appendSingleLayerMediumInjection(
361
+ bgl: readonly GPUBindGroupLayoutEntry[],
362
+ ): GPUBindGroupLayoutEntry[] {
363
+ const start = bgl.length;
364
+ return [
365
+ {
366
+ binding: start,
367
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
368
+ sampler: { type: 'non-filtering' },
369
+ },
370
+ {
371
+ binding: start + 1,
372
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
373
+ texture: { sampleType: 'unfilterable-float', viewDimension: '2d' },
374
+ },
375
+ {
376
+ binding: start + 2,
377
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
378
+ sampler: { type: 'filtering' },
379
+ },
380
+ {
381
+ binding: start + 3,
382
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
383
+ texture: { sampleType: 'float', viewDimension: '2d' },
384
+ },
385
+ {
386
+ binding: start + 4,
387
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
388
+ sampler: { type: 'non-filtering' },
389
+ },
390
+ {
391
+ binding: start + 5,
392
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
393
+ texture: { sampleType: 'unfilterable-float', viewDimension: '2d' },
394
+ },
395
+ ];
396
+ }
397
+
353
398
  // Closed-set length sentinels — the map is the membership owner.
354
399
  export const INJECTION_KIND_LENGTHS = {
355
400
  shadow: SHADOW_INJECTION_LENGTH,
@@ -581,6 +626,7 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
581
626
  },
582
627
  ];
583
628
  const extendedLighting = caps.extendedLighting ?? true;
629
+ const lowLimitCloudBindings = extendedLighting === false && caps.projectorAvailable === false;
584
630
  if (extendedLighting) {
585
631
  entries.push(
586
632
  {
@@ -633,6 +679,23 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
633
679
  visibility: GPU_SHADER_STAGE_VERTEX,
634
680
  buffer: { type: 'uniform', hasDynamicOffset: true },
635
681
  });
682
+ // Cloud direct-solar transport is a renderer-owned view resource. The
683
+ // minimum 16-texture profile has no spare sampled texture lane; its shader
684
+ // variant returns the direct-sun fallback without declaring this pair.
685
+ if (!lowLimitCloudBindings) {
686
+ entries.push(
687
+ {
688
+ binding: 16,
689
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
690
+ texture: { sampleType: 'float', viewDimension: '2d' },
691
+ },
692
+ {
693
+ binding: 17,
694
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
695
+ sampler: { type: 'filtering' },
696
+ },
697
+ );
698
+ }
636
699
  return entries;
637
700
  }
638
701
 
@@ -959,6 +1022,32 @@ export function buildGpuDrivenPbrInstancesBindGroupLayout(
959
1022
  return result.value;
960
1023
  }
961
1024
 
1025
+ /**
1026
+ * Build the slot-3 layout used by direct single-layer-medium draws.
1027
+ *
1028
+ * Direct Surface draws retain their ordinary instance transforms at binding
1029
+ * zero, but consume the same producer-owned ProbeBlend, dynamic page, frame
1030
+ * rows, and shared time resources as the scene-index lane. Binding six is the
1031
+ * per-draw frame-row base; it keeps a local instance index independent from
1032
+ * the renderer's compact scene-index address.
1033
+ */
1034
+ export function buildSurfaceDirectInstancesBindGroupLayout(
1035
+ device: PbrPipelineDevice,
1036
+ caps: PbrCaps,
1037
+ ): BindGroupLayout {
1038
+ if (!caps.storageBuffer) {
1039
+ throw new Error('Direct Surface instances layout requires storage-buffer capability');
1040
+ }
1041
+ const result = device.createBindGroupLayout(
1042
+ buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
1043
+ kind: 'pbr-surface-direct-instances',
1044
+ caps,
1045
+ }),
1046
+ );
1047
+ if (!result.ok) throw result.error;
1048
+ return result.value;
1049
+ }
1050
+
962
1051
  /** Build the four-slot rigid scene-index pipeline layout. */
963
1052
  export function buildGpuDrivenPbrPipelineLayout(
964
1053
  device: PbrPipelineDevice,
@@ -1185,13 +1274,15 @@ export type BglKind =
1185
1274
  | 'pbr-mesh-array'
1186
1275
  | 'pbr-instances'
1187
1276
  | 'pbr-gpu-driven-instances'
1277
+ | 'pbr-surface-direct-instances'
1188
1278
  | 'pbr-skin-mesh-array'
1189
1279
  | 'unlit-material'
1190
1280
  | 'hdrp-7-slot'
1191
1281
  | 'fullscreen-post'
1192
1282
  | 'fullscreen-post-with-params'
1193
1283
  | 'fullscreen-post-with-scene-depth'
1194
- | 'fullscreen-post-with-scene-depth-msaa';
1284
+ | 'fullscreen-post-with-scene-depth-msaa'
1285
+ | 'fullscreen-post-with-paired-msaa';
1195
1286
 
1196
1287
  /**
1197
1288
  * Output shape of {@link buildBindGroupLayoutDescriptor}: matches the RHI
@@ -1434,7 +1525,7 @@ export function buildBindGroupLayoutDescriptor(
1434
1525
  entries: [
1435
1526
  {
1436
1527
  binding: 0,
1437
- visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
1528
+ visibility: GPU_SHADER_STAGE_VERTEX,
1438
1529
  buffer: { type: meshBufType, hasDynamicOffset: false },
1439
1530
  },
1440
1531
  {
@@ -1443,7 +1534,7 @@ export function buildBindGroupLayoutDescriptor(
1443
1534
  // the shared visible bind group can serve both the Standard PBR
1444
1535
  // (binding(2)) and depth-only shadow (binding(1)) consumers.
1445
1536
  binding: 1,
1446
- visibility: GPU_SHADER_STAGE_VERTEX,
1537
+ visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
1447
1538
  buffer: { type: meshBufType, hasDynamicOffset: false },
1448
1539
  },
1449
1540
  {
@@ -1451,6 +1542,71 @@ export function buildBindGroupLayoutDescriptor(
1451
1542
  visibility: GPU_SHADER_STAGE_VERTEX,
1452
1543
  buffer: { type: meshBufType, hasDynamicOffset: false },
1453
1544
  },
1545
+ {
1546
+ // Generic Surface dynamic pages are read by authored Surface
1547
+ // accessors. The binding is present for every scene-index group
1548
+ // so Standard and custom Surface batches share one owner shape.
1549
+ binding: 3,
1550
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1551
+ buffer: { type: meshBufType, hasDynamicOffset: false },
1552
+ },
1553
+ {
1554
+ // Frame time, explicit event ranges, and paired background/depth
1555
+ // facts use separate read-only pages. This keeps live state out
1556
+ // of the material row and leaves skin's address lane untouched.
1557
+ binding: 4,
1558
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1559
+ buffer: { type: meshBufType, hasDynamicOffset: false },
1560
+ },
1561
+ {
1562
+ // Frame time is one frame-global fact. Keeping it outside the
1563
+ // member row prevents a stable frame from issuing one 4-byte
1564
+ // queue write for every visible Surface member.
1565
+ binding: 5,
1566
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1567
+ buffer: { type: 'uniform', hasDynamicOffset: false },
1568
+ },
1569
+ ],
1570
+ };
1571
+ }
1572
+ case 'pbr-surface-direct-instances': {
1573
+ return {
1574
+ label: 'pbr-surface-direct-instances-bgl',
1575
+ entries: [
1576
+ {
1577
+ binding: 0,
1578
+ // Direct instance transforms are consumed only by vs_main. Keep
1579
+ // them out of the fragment-stage storage budget; Surface already
1580
+ // needs the retained ProbeBlend/page/frame records there and the
1581
+ // portable WebGPU limit is eight storage buffers per stage.
1582
+ visibility: GPU_SHADER_STAGE_VERTEX,
1583
+ buffer: { type: 'read-only-storage', hasDynamicOffset: false },
1584
+ },
1585
+ {
1586
+ binding: 1,
1587
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1588
+ buffer: { type: 'read-only-storage', hasDynamicOffset: true },
1589
+ },
1590
+ {
1591
+ binding: 3,
1592
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1593
+ buffer: { type: 'read-only-storage', hasDynamicOffset: false },
1594
+ },
1595
+ {
1596
+ binding: 4,
1597
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1598
+ buffer: { type: 'read-only-storage', hasDynamicOffset: false },
1599
+ },
1600
+ {
1601
+ binding: 5,
1602
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1603
+ buffer: { type: 'uniform', hasDynamicOffset: false },
1604
+ },
1605
+ {
1606
+ binding: 6,
1607
+ visibility: GPU_SHADER_STAGE_VERTEX,
1608
+ buffer: { type: 'uniform', hasDynamicOffset: false },
1609
+ },
1454
1610
  ],
1455
1611
  };
1456
1612
  }
@@ -1504,9 +1660,18 @@ export function buildBindGroupLayoutDescriptor(
1504
1660
  const userRegion = buildPbrMaterialUserRegionEntries(userRegionSchema);
1505
1661
  const afterIbl = [...userRegion, ...appendInjection(userRegion, 'ibl')];
1506
1662
  const afterTransmission = [...afterIbl, ...appendInjection(afterIbl, 'transmission')];
1663
+ const engineRegion =
1664
+ options.caps?.transmissionBackdrop === false &&
1665
+ spec.shader.id !== 'forgeax::single-layer-medium'
1666
+ ? afterIbl
1667
+ : afterTransmission;
1668
+ const afterSurfaceMedium =
1669
+ spec.shader.id === 'forgeax::single-layer-medium'
1670
+ ? [...engineRegion, ...appendSingleLayerMediumInjection(engineRegion)]
1671
+ : engineRegion;
1507
1672
  const merged = [
1508
- ...(options.caps?.transmissionBackdrop === false ? afterIbl : afterTransmission),
1509
- ...appendTextureInjection(afterTransmission, physicalFields),
1673
+ ...afterSurfaceMedium,
1674
+ ...appendTextureInjection(afterSurfaceMedium, physicalFields),
1510
1675
  ];
1511
1676
  // Scene-index Standard variants consume one producer-owned material row
1512
1677
  // after the complete fixed physical range. Keeping it at binding 46
@@ -1518,16 +1683,21 @@ export function buildBindGroupLayoutDescriptor(
1518
1683
  buffer: { type: 'read-only-storage', hasDynamicOffset: false },
1519
1684
  });
1520
1685
  }
1686
+ const entries = [
1687
+ ...merged,
1688
+ ...(spec.shader.id === 'forgeax::single-layer-medium'
1689
+ ? []
1690
+ : [
1691
+ {
1692
+ binding: 47,
1693
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1694
+ texture: { sampleType: 'float' as const, viewDimension: 'cube' as const },
1695
+ },
1696
+ ]),
1697
+ ];
1521
1698
  return {
1522
1699
  label: 'pbr-material-skylight-bgl',
1523
- entries: [
1524
- ...merged,
1525
- {
1526
- binding: 47,
1527
- visibility: GPU_SHADER_STAGE_FRAGMENT,
1528
- texture: { sampleType: 'float', viewDimension: 'cube' },
1529
- },
1530
- ],
1700
+ entries,
1531
1701
  };
1532
1702
  }
1533
1703
  case 'unlit-material': {
@@ -1630,6 +1800,42 @@ export function buildBindGroupLayoutDescriptor(
1630
1800
  ],
1631
1801
  };
1632
1802
  }
1803
+ case 'fullscreen-post-with-paired-msaa': {
1804
+ return {
1805
+ label: 'fullscreen-post-with-paired-msaa-bgl',
1806
+ entries: [
1807
+ {
1808
+ binding: 0,
1809
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1810
+ texture: {
1811
+ sampleType: 'unfilterable-float',
1812
+ viewDimension: '2d',
1813
+ multisampled: true,
1814
+ },
1815
+ },
1816
+ {
1817
+ binding: 1,
1818
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1819
+ sampler: { type: 'filtering' },
1820
+ },
1821
+ {
1822
+ binding: 2,
1823
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1824
+ buffer: { type: 'uniform' },
1825
+ },
1826
+ {
1827
+ binding: 3,
1828
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1829
+ texture: { sampleType: 'depth', viewDimension: '2d', multisampled: true },
1830
+ },
1831
+ {
1832
+ binding: 4,
1833
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1834
+ sampler: { type: 'non-filtering' },
1835
+ },
1836
+ ],
1837
+ };
1838
+ }
1633
1839
  }
1634
1840
  }
1635
1841
 
@@ -0,0 +1,267 @@
1
+ import {
2
+ type GraphAccess,
3
+ type GraphTextureDescriptor,
4
+ type RenderGraphBuilder,
5
+ RenderGraphError,
6
+ } from '@forgeax/engine-render-graph';
7
+ import { err, ok, type Result } from '@forgeax/engine-types';
8
+ import type {
9
+ RenderPipelineFrame,
10
+ RenderPipelineGpuDrivenProjection,
11
+ RenderPipelineSurfaceMediumPair,
12
+ RenderPipelineTarget,
13
+ } from '../render-pipeline';
14
+ import { createRenderPipelineTarget } from '../render-pipeline';
15
+ import { addTypedFullscreenPass, addTypedScenePass } from '../typed-render-graph-primitives';
16
+
17
+ /** Stable renderer-owned post-process identity for the independent depth copy. */
18
+ export const SINGLE_LAYER_MEDIUM_RAW_DEPTH_POST_PROCESS_ID =
19
+ 'forgeax.single-layer-medium-raw-depth' as const;
20
+ export const SINGLE_LAYER_MEDIUM_MSAA_PAIRED_COLOR_POST_PROCESS_ID =
21
+ 'forgeax.single-layer-medium-msaa-paired-color' as const;
22
+ export const SINGLE_LAYER_MEDIUM_MSAA_RAW_DEPTH_POST_PROCESS_ID =
23
+ 'forgeax.single-layer-medium-msaa-raw-depth' as const;
24
+
25
+ export interface SingleLayerMediumMsaaPair {
26
+ readonly color: RenderPipelineTarget;
27
+ readonly depth: RenderPipelineTarget;
28
+ }
29
+
30
+ export interface SingleLayerMediumRawDepthProducerInput {
31
+ readonly graph: RenderGraphBuilder<RenderPipelineFrame>;
32
+ /** Resource/pass prefix; defaults to the opaque scene producer identity. */
33
+ readonly label?: string | undefined;
34
+ /** The already-resolved opaque color keeps the fullscreen primitive's input ABI complete. */
35
+ readonly sourceColor: RenderPipelineTarget;
36
+ /** The opaque depth pass output. It is sampled only by the copy producer. */
37
+ readonly sourceDepth: RenderPipelineTarget;
38
+ /** Must match the Standard scene depth extent (surface or internal resolution). */
39
+ readonly size: GraphTextureDescriptor['size'];
40
+ }
41
+
42
+ /**
43
+ * Produce an independent, single-sample raw-depth texture for Surface media.
44
+ *
45
+ * The graph source is the completed opaque depth pass and the destination is
46
+ * an r32float color target. This intermediate is the only place that samples
47
+ * the hardware depth view; medium materials bind the independent result while
48
+ * writing the scene depth attachment. MSAA is rejected at the producer seam
49
+ * until the backend has an explicit depth resolve policy.
50
+ */
51
+ export function addSingleLayerMediumRawDepthProducer(
52
+ input: SingleLayerMediumRawDepthProducerInput,
53
+ ): Result<RenderPipelineTarget, RenderGraphError> {
54
+ const label = input.label ?? 'single-layer-medium-raw-depth';
55
+ if (input.sourceDepth.sampleCount !== 1) {
56
+ return err(
57
+ new RenderGraphError({
58
+ code: 'resource-descriptor-invalid',
59
+ expected: 'single-layer medium raw-depth producer has a single-sample source depth',
60
+ hint: 'select a resolved 1x depth producer; MSAA depth resolve is not admitted yet',
61
+ detail: {
62
+ resourceLabel: label,
63
+ field: 'sourceDepth.sampleCount',
64
+ expected: '1',
65
+ actual: String(input.sourceDepth.sampleCount),
66
+ },
67
+ }),
68
+ );
69
+ }
70
+
71
+ const rawDepth = createRenderPipelineTarget(input.graph, label, {
72
+ format: 'r32float',
73
+ size: input.size,
74
+ sampleCount: 1,
75
+ });
76
+ if (!rawDepth.ok) return rawDepth;
77
+
78
+ const producer = addTypedFullscreenPass(input.graph, {
79
+ name: `${label}-producer`,
80
+ shader: SINGLE_LAYER_MEDIUM_RAW_DEPTH_POST_PROCESS_ID,
81
+ input: input.sourceColor,
82
+ output: rawDepth.value,
83
+ depth: input.sourceDepth,
84
+ });
85
+ if (!producer.ok) return producer;
86
+ return ok(rawDepth.value);
87
+ }
88
+
89
+ /**
90
+ * Resolve a four-sample color/depth pair by selecting the nearest depth sample
91
+ * and the color at that exact sample index. This is deliberately separate
92
+ * from WebGPU's averaging color resolve, which cannot preserve the opaque or
93
+ * nearest-water sample associated with the selected depth.
94
+ */
95
+ export function addSingleLayerMediumMsaaPairProducer(input: {
96
+ readonly graph: RenderGraphBuilder<RenderPipelineFrame>;
97
+ readonly label: string;
98
+ readonly sourceColor: RenderPipelineTarget;
99
+ readonly sourceDepth: RenderPipelineTarget;
100
+ readonly size: GraphTextureDescriptor['size'];
101
+ }): Result<SingleLayerMediumMsaaPair, RenderGraphError> {
102
+ if (input.sourceColor.sampleCount !== 4 || input.sourceDepth.sampleCount !== 4) {
103
+ return err(
104
+ new RenderGraphError({
105
+ code: 'resource-descriptor-invalid',
106
+ expected: 'single-layer medium paired MSAA producer has 4x color and depth inputs',
107
+ hint: 'route 1x inputs through the single-sample raw-depth producer',
108
+ detail: {
109
+ resourceLabel: input.label,
110
+ field: 'source.sampleCount',
111
+ expected: 'color=4,depth=4',
112
+ actual: `color=${input.sourceColor.sampleCount},depth=${input.sourceDepth.sampleCount}`,
113
+ },
114
+ }),
115
+ );
116
+ }
117
+ const color = createRenderPipelineTarget(input.graph, `${input.label}-color`, {
118
+ format: input.sourceColor.format,
119
+ size: input.size,
120
+ sampleCount: 1,
121
+ ...(input.sourceColor.domain === undefined ? {} : { domain: input.sourceColor.domain }),
122
+ });
123
+ if (!color.ok) return color;
124
+ const depth = createRenderPipelineTarget(input.graph, `${input.label}-depth`, {
125
+ format: 'r32float',
126
+ size: input.size,
127
+ sampleCount: 1,
128
+ });
129
+ if (!depth.ok) return depth;
130
+ const colorProducer = addTypedFullscreenPass(input.graph, {
131
+ name: `${input.label}-color-producer`,
132
+ shader: SINGLE_LAYER_MEDIUM_MSAA_PAIRED_COLOR_POST_PROCESS_ID,
133
+ input: input.sourceColor,
134
+ output: color.value,
135
+ depth: input.sourceDepth,
136
+ });
137
+ if (!colorProducer.ok) return colorProducer;
138
+ const depthProducer = addTypedFullscreenPass(input.graph, {
139
+ name: `${input.label}-depth-producer`,
140
+ shader: SINGLE_LAYER_MEDIUM_MSAA_RAW_DEPTH_POST_PROCESS_ID,
141
+ input: input.sourceColor,
142
+ output: depth.value,
143
+ depth: input.sourceDepth,
144
+ });
145
+ if (!depthProducer.ok) return depthProducer;
146
+ return ok({ color: color.value, depth: depth.value });
147
+ }
148
+
149
+ /** Inputs shared by the two graph passes owned by the Surface model. */
150
+ export interface SingleLayerMediumPassInput {
151
+ readonly graph: RenderGraphBuilder<RenderPipelineFrame>;
152
+ readonly size: GraphTextureDescriptor['size'];
153
+ readonly nearestLayer: RenderPipelineTarget;
154
+ readonly nearestDepth: RenderPipelineTarget;
155
+ readonly color: RenderPipelineTarget;
156
+ readonly colorResolve?: RenderPipelineTarget | undefined;
157
+ readonly depth: RenderPipelineTarget;
158
+ readonly sampled?: readonly RenderPipelineTarget[] | undefined;
159
+ readonly directionalShadow?: RenderPipelineTarget | undefined;
160
+ readonly spotShadow?: RenderPipelineTarget | undefined;
161
+ /** Optional producer-owned cloud shadow bound through the Standard frame group. */
162
+ readonly cloudShadow?: RenderPipelineTarget | undefined;
163
+ readonly ssao?: RenderPipelineTarget | undefined;
164
+ readonly extraAccesses?: readonly GraphAccess[] | undefined;
165
+ /** Producer-owned pair of opaque color and sampled raw-depth facts. */
166
+ readonly surfacePair: RenderPipelineSurfaceMediumPair;
167
+ readonly gpuDriven?: RenderPipelineGpuDrivenProjection | undefined;
168
+ }
169
+
170
+ /**
171
+ * Admit the nearest-layer and color Surface submissions to the existing
172
+ * Standard graph only when the producer supplied a paired sampled raw depth.
173
+ * The pair is deliberately an input: this helper does not invent a backdrop,
174
+ * copy depth, or turn an unavailable fact into a graph resource.
175
+ */
176
+ export function addSingleLayerMediumPasses(
177
+ input: SingleLayerMediumPassInput,
178
+ ): Result<void, RenderGraphError> {
179
+ const pair = input.surfacePair;
180
+ if (pair.rawDepth.status === 'unavailable') {
181
+ return err(
182
+ new RenderGraphError({
183
+ code: 'resource-descriptor-invalid',
184
+ expected: 'single-layer medium consumes a graph-paired sampled raw depth',
185
+ hint: 'enable an owner-approved depth-copy producer before admitting the Surface passes',
186
+ detail: {
187
+ resourceLabel: 'single-layer-medium',
188
+ field: 'surfacePair.rawDepth',
189
+ expected: 'available sampled depth view',
190
+ actual: pair.rawDepth.reason,
191
+ },
192
+ }),
193
+ );
194
+ }
195
+ const sampled = input.sampled ?? [];
196
+ const nearest = addTypedScenePass(input.graph, {
197
+ name: 'single-layer-medium-nearest-layer',
198
+ color: input.nearestLayer,
199
+ depth: input.nearestDepth,
200
+ sampled,
201
+ ...(input.directionalShadow === undefined
202
+ ? {}
203
+ : { directionalShadow: input.directionalShadow }),
204
+ ...(input.spotShadow === undefined ? {} : { spotShadow: input.spotShadow }),
205
+ ...(input.cloudShadow === undefined ? {} : { cloudShadow: input.cloudShadow }),
206
+ ...(input.ssao === undefined ? {} : { ssao: input.ssao }),
207
+ selector: { LightMode: ['Forward'] },
208
+ colorLoadOp: 'clear',
209
+ depthLoadOp: 'clear',
210
+ recordMode: 'single-layer-medium-nearest-layer',
211
+ transmissionBackdrop: pair.opaqueColor,
212
+ surfacePair: pair,
213
+ gpuDrivenFilter: 'single-layer-medium',
214
+ ...(input.extraAccesses === undefined ? {} : { extraAccesses: input.extraAccesses }),
215
+ ...(input.gpuDriven === undefined ? {} : { gpuDriven: input.gpuDriven }),
216
+ });
217
+ if (!nearest.ok) return nearest;
218
+
219
+ const nearestPair =
220
+ input.nearestLayer.sampleCount === 4
221
+ ? addSingleLayerMediumMsaaPairProducer({
222
+ graph: input.graph,
223
+ label: 'single-layer-medium-nearest-resolve',
224
+ sourceColor: input.nearestLayer,
225
+ sourceDepth: input.nearestDepth,
226
+ size: input.size,
227
+ })
228
+ : (() => {
229
+ const depth = addSingleLayerMediumRawDepthProducer({
230
+ graph: input.graph,
231
+ label: 'single-layer-medium-nearest-depth-sampled',
232
+ sourceColor: input.nearestLayer,
233
+ sourceDepth: input.nearestDepth,
234
+ size: input.size,
235
+ });
236
+ return depth.ok ? ok({ color: input.nearestLayer, depth: depth.value }) : depth;
237
+ })();
238
+ if (!nearestPair.ok) return nearestPair;
239
+
240
+ const colorSampled = [...sampled, nearestPair.value.color];
241
+ const color = addTypedScenePass(input.graph, {
242
+ name: 'single-layer-medium-color',
243
+ color: input.color,
244
+ ...(input.colorResolve === undefined ? {} : { resolve: input.colorResolve }),
245
+ depth: input.depth,
246
+ sampled: colorSampled,
247
+ ...(input.directionalShadow === undefined
248
+ ? {}
249
+ : { directionalShadow: input.directionalShadow }),
250
+ ...(input.spotShadow === undefined ? {} : { spotShadow: input.spotShadow }),
251
+ ...(input.cloudShadow === undefined ? {} : { cloudShadow: input.cloudShadow }),
252
+ ...(input.ssao === undefined ? {} : { ssao: input.ssao }),
253
+ selector: { LightMode: ['Forward'] },
254
+ colorLoadOp: 'load',
255
+ depthLoadOp: 'load',
256
+ recordMode: 'single-layer-medium-color',
257
+ transmissionBackdrop: pair.opaqueColor,
258
+ surfacePair: pair,
259
+ surfaceNearestLayer: nearestPair.value.color.view,
260
+ surfaceNearestDepth: nearestPair.value.depth.view,
261
+ gpuDrivenFilter: 'single-layer-medium',
262
+ ...(input.extraAccesses === undefined ? {} : { extraAccesses: input.extraAccesses }),
263
+ ...(input.gpuDriven === undefined ? {} : { gpuDriven: input.gpuDriven }),
264
+ });
265
+ if (!color.ok) return color;
266
+ return ok(undefined);
267
+ }