@forgeax/engine-render 0.1.20 → 0.1.23

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 (645) hide show
  1. package/README.md +365 -29
  2. package/dist/assembly/backend-contract.d.ts +13 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/device-feature-admission.d.ts +18 -0
  5. package/dist/assembly/device-feature-admission.d.ts.map +1 -0
  6. package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
  7. package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
  8. package/dist/assembly/factory.d.ts +30 -19
  9. package/dist/assembly/factory.d.ts.map +1 -1
  10. package/dist/assembly/host-contract.d.ts +19 -0
  11. package/dist/assembly/host-contract.d.ts.map +1 -1
  12. package/dist/assembly/render-target-host.d.ts +46 -0
  13. package/dist/assembly/render-target-host.d.ts.map +1 -0
  14. package/dist/assets/render-asset-port.d.ts.map +1 -1
  15. package/dist/authoring.mjs +4 -1
  16. package/dist/authoring.mjs.map +1 -1
  17. package/dist/capture/cube-views.d.ts +21 -0
  18. package/dist/capture/cube-views.d.ts.map +1 -0
  19. package/dist/capture/scheduler.d.ts +54 -0
  20. package/dist/capture/scheduler.d.ts.map +1 -0
  21. package/dist/{chunk-PCHBPYML.mjs → chunk-4L3P6DT5.mjs} +2 -2
  22. package/dist/chunk-4L3P6DT5.mjs.map +1 -0
  23. package/dist/{chunk-VFPLTKCU.mjs → chunk-4NPUASZR.mjs} +15 -4
  24. package/dist/chunk-4NPUASZR.mjs.map +1 -0
  25. package/dist/chunk-DIYW3M5D.mjs +5085 -0
  26. package/dist/chunk-DIYW3M5D.mjs.map +1 -0
  27. package/dist/chunk-FBC4R44J.mjs +1003 -0
  28. package/dist/chunk-FBC4R44J.mjs.map +1 -0
  29. package/dist/{chunk-CDTWTHZR.mjs → chunk-FF7K3FSO.mjs} +474 -168
  30. package/dist/chunk-FF7K3FSO.mjs.map +1 -0
  31. package/dist/chunk-HZUPSYW7.mjs +1104 -0
  32. package/dist/chunk-HZUPSYW7.mjs.map +1 -0
  33. package/dist/{chunk-TBQJOK2L.mjs → chunk-QODA5UKU.mjs} +321 -269
  34. package/dist/chunk-QODA5UKU.mjs.map +1 -0
  35. package/dist/chunk-YALPS44A.mjs +296 -0
  36. package/dist/chunk-YALPS44A.mjs.map +1 -0
  37. package/dist/{chunk-4XINDLAY.mjs → chunk-ZUWKAZ2I.mjs} +1963 -2178
  38. package/dist/chunk-ZUWKAZ2I.mjs.map +1 -0
  39. package/dist/cluster-binner.d.ts +5 -0
  40. package/dist/cluster-binner.d.ts.map +1 -1
  41. package/dist/components/camera.d.ts +1 -0
  42. package/dist/components/camera.d.ts.map +1 -1
  43. package/dist/components/cube-camera.d.ts +20 -0
  44. package/dist/components/cube-camera.d.ts.map +1 -0
  45. package/dist/components/directional-light.d.ts +11 -2
  46. package/dist/components/directional-light.d.ts.map +1 -1
  47. package/dist/components/directional-shadow-filter.d.ts +25 -0
  48. package/dist/components/directional-shadow-filter.d.ts.map +1 -0
  49. package/dist/components/index.d.ts +5 -0
  50. package/dist/components/index.d.ts.map +1 -1
  51. package/dist/components/light-helpers.d.ts +4 -0
  52. package/dist/components/light-helpers.d.ts.map +1 -1
  53. package/dist/components/light-probe.d.ts +9 -0
  54. package/dist/components/light-probe.d.ts.map +1 -0
  55. package/dist/components/rect-area-light.d.ts +12 -0
  56. package/dist/components/rect-area-light.d.ts.map +1 -0
  57. package/dist/components/reflection-probe.d.ts +17 -0
  58. package/dist/components/reflection-probe.d.ts.map +1 -0
  59. package/dist/components/scene-instance.d.ts +4 -0
  60. package/dist/components/scene-instance.d.ts.map +1 -1
  61. package/dist/components/spot-light.d.ts +3 -0
  62. package/dist/components/spot-light.d.ts.map +1 -1
  63. package/dist/construct-renderer.mjs +14836 -9620
  64. package/dist/construct-renderer.mjs.map +1 -1
  65. package/dist/device/gpu-residency.d.ts +8 -1
  66. package/dist/device/gpu-residency.d.ts.map +1 -1
  67. package/dist/device/lifecycle-transaction.d.ts +2 -0
  68. package/dist/device/lifecycle-transaction.d.ts.map +1 -0
  69. package/dist/environment/frame.d.ts.map +1 -1
  70. package/dist/environment/lifecycle.d.ts +5 -0
  71. package/dist/environment/lifecycle.d.ts.map +1 -1
  72. package/dist/errors/gpu-driven.d.ts +26 -0
  73. package/dist/errors/gpu-driven.d.ts.map +1 -0
  74. package/dist/errors/index.d.ts +1 -0
  75. package/dist/errors/index.d.ts.map +1 -1
  76. package/dist/errors/recover.d.ts +9 -1
  77. package/dist/errors/recover.d.ts.map +1 -1
  78. package/dist/errors/render.d.ts +166 -93
  79. package/dist/errors/render.d.ts.map +1 -1
  80. package/dist/extract/directional-shadow-projection.d.ts +23 -0
  81. package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
  82. package/dist/extract/environment.d.ts +14 -0
  83. package/dist/extract/environment.d.ts.map +1 -1
  84. package/dist/extract/gpu-driven.d.ts +50 -0
  85. package/dist/extract/gpu-driven.d.ts.map +1 -0
  86. package/dist/extract/visibility.d.ts.map +1 -1
  87. package/dist/features/fullscreen.d.ts.map +1 -1
  88. package/dist/features/targets.d.ts.map +1 -1
  89. package/dist/features/types.d.ts +10 -0
  90. package/dist/features/types.d.ts.map +1 -1
  91. package/dist/fullscreen-post-process-pass.d.ts +13 -2
  92. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  93. package/dist/gpu-driven/batch-topology.d.ts +34 -0
  94. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  95. package/dist/gpu-driven/prepared-draw.d.ts +63 -0
  96. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
  97. package/dist/gpu-driven/production-raster.d.ts +97 -2
  98. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  99. package/dist/gpu-driven/view-gpu.d.ts +64 -1
  100. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  101. package/dist/gpu-scene-schema.d.ts +14 -0
  102. package/dist/gpu-scene-schema.d.ts.map +1 -1
  103. package/dist/gpu-scene.d.ts +8 -1
  104. package/dist/gpu-scene.d.ts.map +1 -1
  105. package/dist/gpu-usage.d.ts +0 -1
  106. package/dist/gpu-usage.d.ts.map +1 -1
  107. package/dist/hdrp-buffers.d.ts +21 -19
  108. package/dist/hdrp-buffers.d.ts.map +1 -1
  109. package/dist/ibl/IblPipelineCache.d.ts +4 -0
  110. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  111. package/dist/ibl/kernel-cache.d.ts +36 -0
  112. package/dist/ibl/kernel-cache.d.ts.map +1 -0
  113. package/dist/index.d.ts +39 -3
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.mjs +91 -6
  116. package/dist/index.mjs.map +1 -1
  117. package/dist/inspection-types.d.ts +214 -1
  118. package/dist/inspection-types.d.ts.map +1 -1
  119. package/dist/instances-derived-bounds.d.ts +50 -0
  120. package/dist/instances-derived-bounds.d.ts.map +1 -0
  121. package/dist/internal.d.ts +9 -0
  122. package/dist/internal.d.ts.map +1 -1
  123. package/dist/internal.mjs +23 -2
  124. package/dist/internal.mjs.map +1 -1
  125. package/dist/light-buffer-layout.d.ts +58 -140
  126. package/dist/light-buffer-layout.d.ts.map +1 -1
  127. package/dist/materials.d.ts.map +1 -1
  128. package/dist/mesh-material-bindings.d.ts +54 -0
  129. package/dist/mesh-material-bindings.d.ts.map +1 -1
  130. package/dist/pbr-pipeline.d.ts +38 -14
  131. package/dist/pbr-pipeline.d.ts.map +1 -1
  132. package/dist/pipeline/standard-forward-lane.d.ts +2 -1
  133. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  134. package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
  135. package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
  136. package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
  137. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
  138. package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
  139. package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
  140. package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
  141. package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
  142. package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
  143. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
  144. package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
  145. package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
  146. package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
  147. package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
  148. package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
  149. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
  150. package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
  151. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
  152. package/dist/pipeline/standard-pipeline.d.ts +4 -13
  153. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  154. package/dist/pipeline/standard-post.d.ts.map +1 -1
  155. package/dist/pipeline/standard-profile.d.ts +5 -26
  156. package/dist/pipeline/standard-profile.d.ts.map +1 -1
  157. package/dist/pipeline-builder.d.ts +2 -0
  158. package/dist/pipeline-builder.d.ts.map +1 -1
  159. package/dist/pipeline-spec.d.ts +40 -7
  160. package/dist/pipeline-spec.d.ts.map +1 -1
  161. package/dist/plugin.d.ts.map +1 -1
  162. package/dist/point-shadow-inspection.d.ts +21 -0
  163. package/dist/point-shadow-inspection.d.ts.map +1 -0
  164. package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
  165. package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
  166. package/dist/prepare/extended-lighting/resources.d.ts +72 -0
  167. package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
  168. package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
  169. package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
  170. package/dist/prepare/extended-lighting/state.d.ts +24 -0
  171. package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
  172. package/dist/record/frame-lighting.d.ts +33 -36
  173. package/dist/record/frame-lighting.d.ts.map +1 -1
  174. package/dist/record/frame-snapshot.d.ts +78 -24
  175. package/dist/record/frame-snapshot.d.ts.map +1 -1
  176. package/dist/record/frame-targets.d.ts +5 -0
  177. package/dist/record/frame-targets.d.ts.map +1 -1
  178. package/dist/record/frame.d.ts +16 -6
  179. package/dist/record/frame.d.ts.map +1 -1
  180. package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
  181. package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
  182. package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
  183. package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
  184. package/dist/record/gpu-pass-timing/index.d.ts +8 -0
  185. package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
  186. package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
  187. package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
  188. package/dist/record/gpu-pass-timing/session.d.ts +43 -0
  189. package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
  190. package/dist/record/gpu-timing.d.ts +20 -3
  191. package/dist/record/gpu-timing.d.ts.map +1 -1
  192. package/dist/record/helpers.d.ts +0 -20
  193. package/dist/record/helpers.d.ts.map +1 -1
  194. package/dist/record/main-pass-geometry.d.ts +6 -1
  195. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  196. package/dist/record/main-pass-material.d.ts +25 -2
  197. package/dist/record/main-pass-material.d.ts.map +1 -1
  198. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  199. package/dist/record/main-pass.d.ts +2 -0
  200. package/dist/record/main-pass.d.ts.map +1 -1
  201. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  202. package/dist/record/render-context.d.ts +98 -6
  203. package/dist/record/render-context.d.ts.map +1 -1
  204. package/dist/record/shadow-pass.d.ts.map +1 -1
  205. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  206. package/dist/record/typed-frame-graph.d.ts +119 -4
  207. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  208. package/dist/record/view-ubo.d.ts +7 -5
  209. package/dist/record/view-ubo.d.ts.map +1 -1
  210. package/dist/reflection/filter.d.ts +22 -0
  211. package/dist/reflection/filter.d.ts.map +1 -0
  212. package/dist/reflection/gpu-table.d.ts +25 -0
  213. package/dist/reflection/gpu-table.d.ts.map +1 -0
  214. package/dist/reflection/inspection.d.ts +10 -0
  215. package/dist/reflection/inspection.d.ts.map +1 -0
  216. package/dist/reflection/projection.d.ts +140 -0
  217. package/dist/reflection/projection.d.ts.map +1 -0
  218. package/dist/reflection/record-owner.d.ts +60 -0
  219. package/dist/reflection/record-owner.d.ts.map +1 -0
  220. package/dist/render-contract.d.ts +62 -14
  221. package/dist/render-contract.d.ts.map +1 -1
  222. package/dist/render-graph-primitives.d.ts +1 -0
  223. package/dist/render-graph-primitives.d.ts.map +1 -1
  224. package/dist/render-pipeline.d.ts +49 -2
  225. package/dist/render-pipeline.d.ts.map +1 -1
  226. package/dist/render-system-extract.d.ts +160 -31
  227. package/dist/render-system-extract.d.ts.map +1 -1
  228. package/dist/render-system.d.ts +28 -2
  229. package/dist/render-system.d.ts.map +1 -1
  230. package/dist/renderer.d.ts +43 -0
  231. package/dist/renderer.d.ts.map +1 -0
  232. package/dist/scene/probe-blend-record.d.ts +22 -0
  233. package/dist/scene/probe-blend-record.d.ts.map +1 -0
  234. package/dist/scene/probe-blend.d.ts +142 -0
  235. package/dist/scene/probe-blend.d.ts.map +1 -0
  236. package/dist/scene/render-scene-types.d.ts +0 -6
  237. package/dist/scene/render-scene-types.d.ts.map +1 -1
  238. package/dist/scene/render-scene.d.ts +117 -9
  239. package/dist/scene/render-scene.d.ts.map +1 -1
  240. package/dist/scene/visibility/bounds.d.ts +20 -0
  241. package/dist/scene/visibility/bounds.d.ts.map +1 -0
  242. package/dist/scene/visibility/budget.d.ts +16 -0
  243. package/dist/scene/visibility/budget.d.ts.map +1 -0
  244. package/dist/scene/visibility/facet.d.ts +73 -0
  245. package/dist/scene/visibility/facet.d.ts.map +1 -0
  246. package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
  247. package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
  248. package/dist/scene/visibility/gpu-lod.d.ts +46 -0
  249. package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
  250. package/dist/scene/visibility/inspection.d.ts +132 -0
  251. package/dist/scene/visibility/inspection.d.ts.map +1 -0
  252. package/dist/scene/visibility/lod-selector.d.ts +25 -0
  253. package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
  254. package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
  255. package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
  256. package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
  257. package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
  258. package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
  259. package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
  260. package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
  261. package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
  262. package/dist/scene/visibility/types.d.ts +34 -0
  263. package/dist/scene/visibility/types.d.ts.map +1 -0
  264. package/dist/shadow-atlas.d.ts +3 -3
  265. package/dist/shadow-atlas.d.ts.map +1 -1
  266. package/dist/ssao-buffers.d.ts +3 -0
  267. package/dist/ssao-buffers.d.ts.map +1 -1
  268. package/dist/ssr/admission.d.ts +122 -0
  269. package/dist/ssr/admission.d.ts.map +1 -0
  270. package/dist/ssr/composition.d.ts +32 -0
  271. package/dist/ssr/composition.d.ts.map +1 -0
  272. package/dist/ssr/errors.d.ts +39 -0
  273. package/dist/ssr/errors.d.ts.map +1 -0
  274. package/dist/ssr/identity.d.ts +13 -0
  275. package/dist/ssr/identity.d.ts.map +1 -0
  276. package/dist/systems/skin-palette-allocator.d.ts +1 -1
  277. package/dist/targets/contracts.d.ts +66 -0
  278. package/dist/targets/contracts.d.ts.map +1 -0
  279. package/dist/targets/graph-projection.d.ts +29 -0
  280. package/dist/targets/graph-projection.d.ts.map +1 -0
  281. package/dist/targets/material-source.d.ts +34 -0
  282. package/dist/targets/material-source.d.ts.map +1 -0
  283. package/dist/targets/owner.d.ts +32 -0
  284. package/dist/targets/owner.d.ts.map +1 -0
  285. package/dist/targets/physical.d.ts +18 -0
  286. package/dist/targets/physical.d.ts.map +1 -0
  287. package/dist/targets/readback.d.ts +39 -0
  288. package/dist/targets/readback.d.ts.map +1 -0
  289. package/dist/temporal/frame-coordinator.d.ts +13 -0
  290. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  291. package/dist/temporal/frame.d.ts +2 -0
  292. package/dist/temporal/frame.d.ts.map +1 -1
  293. package/dist/temporal/index.mjs +6 -5
  294. package/dist/temporal/view.d.ts +7 -0
  295. package/dist/temporal/view.d.ts.map +1 -1
  296. package/dist/tilemap-chunk-extract-system.d.ts +1 -1
  297. package/dist/typed-render-graph-primitives.d.ts +5 -1
  298. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  299. package/dist/typed-shadow-passes.d.ts +1 -1
  300. package/dist/typed-shadow-passes.d.ts.map +1 -1
  301. package/dist/volume/passes.d.ts +9 -5
  302. package/dist/volume/passes.d.ts.map +1 -1
  303. package/package.json +20 -20
  304. package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
  305. package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
  306. package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
  307. package/src/__tests__/cluster-binner.unit.test.ts +35 -0
  308. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +12 -2
  309. package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
  310. package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
  311. package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
  312. package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
  313. package/src/__tests__/cube-camera.integration.test.ts +42 -0
  314. package/src/__tests__/detached-inspection.integration.test.ts +6 -0
  315. package/src/__tests__/device-feature-admission.unit.test.ts +85 -0
  316. package/src/__tests__/direct-light-snapshot.unit.test.ts +62 -6
  317. package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
  318. package/src/__tests__/environment-generation.integration.test.ts +16 -0
  319. package/src/__tests__/evidence-identity.ts +13 -0
  320. package/src/__tests__/evidence-identity.unit.test.ts +24 -0
  321. package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
  322. package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
  323. package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
  324. package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
  325. package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
  326. package/src/__tests__/factory-contract.integration.test.ts +288 -29
  327. package/src/__tests__/fog-component.unit.test.ts +67 -0
  328. package/src/__tests__/fog.integration.test.ts +86 -0
  329. package/src/__tests__/frame-observation.contract.test.ts +15 -0
  330. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
  331. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
  332. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -8
  333. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +18 -1
  334. package/src/__tests__/gpu-driven-production.integration.test.ts +579 -17
  335. package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
  336. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
  337. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +101 -6
  338. package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
  339. package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
  340. package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
  341. package/src/__tests__/gpu-lod-evidence.ts +188 -0
  342. package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
  343. package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
  344. package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
  345. package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
  346. package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
  347. package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
  348. package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
  349. package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
  350. package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
  351. package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
  352. package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
  353. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
  354. package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
  355. package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
  356. package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
  357. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
  358. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
  359. package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
  360. package/src/__tests__/gpu-scene.unit.test.ts +49 -3
  361. package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
  362. package/src/__tests__/instances-culling.integration.test.ts +94 -0
  363. package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
  364. package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
  365. package/src/__tests__/light-inspection.unit.test.ts +55 -0
  366. package/src/__tests__/light-resource-error.unit.test.ts +43 -0
  367. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
  368. package/src/__tests__/lod-bounds.unit.test.ts +42 -0
  369. package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
  370. package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
  371. package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
  372. package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
  373. package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
  374. package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
  375. package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
  376. package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
  377. package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
  378. package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
  379. package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
  380. package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
  381. package/src/__tests__/lod-selector.profile.test.ts +35 -0
  382. package/src/__tests__/lod-selector.unit.test.ts +68 -0
  383. package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
  384. package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
  385. package/src/__tests__/ltc-resources.unit.test.ts +32 -0
  386. package/src/__tests__/material-contract-inventory.unit.test.ts +17 -0
  387. package/src/__tests__/material-observation.integration.test.ts +101 -0
  388. package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
  389. package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
  390. package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
  391. package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
  392. package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
  393. package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
  394. package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
  395. package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
  396. package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
  397. package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
  398. package/src/__tests__/occlusion-query.evidence.ts +178 -0
  399. package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
  400. package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
  401. package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
  402. package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
  403. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
  404. package/src/__tests__/probe-bindings.unit.test.ts +200 -0
  405. package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
  406. package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
  407. package/src/__tests__/probe-capacity.integration.test.ts +97 -0
  408. package/src/__tests__/probe-recovery.integration.test.ts +104 -0
  409. package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
  410. package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
  411. package/src/__tests__/profiler-phase-token.test.ts +1 -0
  412. package/src/__tests__/public-surface.test-d.ts +10 -0
  413. package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
  414. package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
  415. package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
  416. package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
  417. package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
  418. package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
  419. package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
  420. package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
  421. package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
  422. package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
  423. package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
  424. package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
  425. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
  426. package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
  427. package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
  428. package/src/__tests__/render-error-code-owner.test-d.ts +19 -3
  429. package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
  430. package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
  431. package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
  432. package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
  433. package/src/__tests__/render-target-admission.unit.test.ts +80 -0
  434. package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
  435. package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
  436. package/src/__tests__/render-target-material-source.test-d.ts +30 -0
  437. package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
  438. package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
  439. package/src/__tests__/render-target-owner.unit.test.ts +122 -0
  440. package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
  441. package/src/__tests__/render-target-public-schema.json +107 -0
  442. package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
  443. package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
  444. package/src/__tests__/render-target-readback.integration.test.ts +90 -0
  445. package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
  446. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +124 -0
  447. package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
  448. package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
  449. package/src/__tests__/skin-motion-regression.unit.test.ts +154 -0
  450. package/src/__tests__/skinned-shadow-caster.test.ts +13 -4
  451. package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
  452. package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
  453. package/src/__tests__/ssr-composition.unit.test.ts +46 -0
  454. package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
  455. package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
  456. package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
  457. package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
  458. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +299 -0
  459. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +15 -5
  460. package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
  461. package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
  462. package/src/__tests__/standard-lighting-write.unit.test.ts +441 -0
  463. package/src/__tests__/standard-lighting.integration.test.ts +67 -0
  464. package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
  465. package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
  466. package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
  467. package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -38
  468. package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
  469. package/src/__tests__/temporal-view.unit.test.ts +3 -3
  470. package/src/__tests__/transmission-prewarm.unit.test.ts +69 -0
  471. package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
  472. package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
  473. package/src/__tests__/visibility-budget.integration.test.ts +140 -0
  474. package/src/__tests__/visibility-budget.unit.test.ts +70 -0
  475. package/src/__tests__/visibility-extract.integration.test.ts +11 -6
  476. package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
  477. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
  478. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
  479. package/src/assembly/backend-contract.ts +13 -0
  480. package/src/assembly/device-feature-admission.ts +80 -0
  481. package/src/assembly/directional-shadow-inspection.ts +122 -0
  482. package/src/assembly/factory.ts +1411 -366
  483. package/src/assembly/host-contract.ts +35 -0
  484. package/src/assembly/render-target-host.ts +847 -0
  485. package/src/assets/asset-decoders.ts +1 -1
  486. package/src/assets/render-asset-port.ts +7 -1
  487. package/src/capture/cube-views.ts +69 -0
  488. package/src/capture/scheduler.ts +265 -0
  489. package/src/cluster-binner.ts +31 -0
  490. package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
  491. package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
  492. package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
  493. package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
  494. package/src/components/camera.ts +4 -0
  495. package/src/components/cube-camera.ts +52 -0
  496. package/src/components/directional-light.ts +22 -2
  497. package/src/components/directional-shadow-filter.ts +57 -0
  498. package/src/components/index.ts +5 -0
  499. package/src/components/light-helpers.ts +133 -8
  500. package/src/components/light-probe.ts +13 -0
  501. package/src/components/rect-area-light.ts +15 -0
  502. package/src/components/reflection-probe.ts +49 -0
  503. package/src/components/scene-instance.ts +6 -0
  504. package/src/components/spot-light.ts +3 -0
  505. package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
  506. package/src/device/gpu-residency.ts +140 -9
  507. package/src/device/lifecycle-transaction.ts +12 -0
  508. package/src/environment/frame.ts +6 -24
  509. package/src/environment/lifecycle.ts +20 -1
  510. package/src/errors/gpu-driven.ts +92 -0
  511. package/src/errors/index.ts +1 -0
  512. package/src/errors/recover.ts +32 -0
  513. package/src/errors/render.ts +341 -143
  514. package/src/extract/camera.ts +3 -3
  515. package/src/extract/directional-shadow-projection.ts +61 -0
  516. package/src/extract/environment.ts +57 -0
  517. package/src/extract/gpu-driven.ts +108 -0
  518. package/src/extract/visibility.ts +2 -1
  519. package/src/features/fullscreen.ts +3 -0
  520. package/src/features/targets.ts +4 -1
  521. package/src/features/types.ts +10 -0
  522. package/src/fullscreen-post-process-pass.ts +43 -2
  523. package/src/gpu-driven/batch-topology.ts +207 -28
  524. package/src/gpu-driven/prepared-draw.ts +208 -0
  525. package/src/gpu-driven/production-raster.ts +953 -43
  526. package/src/gpu-driven/view-gpu.ts +411 -29
  527. package/src/gpu-scene-schema.ts +13 -0
  528. package/src/gpu-scene.ts +140 -64
  529. package/src/gpu-usage.ts +0 -1
  530. package/src/hdrp-buffers.ts +169 -63
  531. package/src/ibl/IblPipelineCache.ts +11 -0
  532. package/src/ibl/kernel-cache.ts +88 -0
  533. package/src/index.ts +222 -0
  534. package/src/inspection-types.ts +276 -1
  535. package/src/instances-derived-bounds.ts +171 -0
  536. package/src/internal.ts +38 -0
  537. package/src/light-buffer-layout.ts +155 -310
  538. package/src/materials.ts +16 -2
  539. package/src/mesh-material-bindings.ts +132 -0
  540. package/src/pbr-pipeline.ts +255 -60
  541. package/src/pipeline/standard-forward-lane.ts +93 -16
  542. package/src/pipeline/standard-lighting/errors.ts +6 -0
  543. package/src/pipeline/standard-lighting/graph.ts +158 -0
  544. package/src/pipeline/standard-lighting/inspection.ts +88 -0
  545. package/src/pipeline/standard-lighting/layout.ts +31 -0
  546. package/src/pipeline/standard-lighting/light-frame.ts +35 -0
  547. package/src/pipeline/standard-lighting/membership.ts +43 -0
  548. package/src/pipeline/standard-lighting/prepare.ts +37 -0
  549. package/src/pipeline/standard-lighting/topology.ts +120 -0
  550. package/src/pipeline/standard-lighting/transport.ts +78 -0
  551. package/src/pipeline/standard-pipeline.ts +124 -193
  552. package/src/pipeline/standard-post.ts +26 -7
  553. package/src/pipeline/standard-profile.ts +17 -47
  554. package/src/pipeline-builder.ts +5 -2
  555. package/src/pipeline-spec.ts +95 -21
  556. package/src/plugin.ts +4 -0
  557. package/src/point-shadow-inspection.ts +55 -0
  558. package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
  559. package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
  560. package/src/prepare/extended-lighting/resources.ts +389 -0
  561. package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
  562. package/src/prepare/extended-lighting/state.ts +92 -0
  563. package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
  564. package/src/record/__tests__/temporal-payload.unit.test.ts +64 -1
  565. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
  566. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
  567. package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
  568. package/src/record/frame-lighting.ts +591 -452
  569. package/src/record/frame-snapshot.ts +92 -39
  570. package/src/record/frame-targets.ts +17 -0
  571. package/src/record/frame.ts +662 -158
  572. package/src/record/gpu-pass-timing/contract.ts +180 -0
  573. package/src/record/gpu-pass-timing/errors.ts +34 -0
  574. package/src/record/gpu-pass-timing/index.ts +37 -0
  575. package/src/record/gpu-pass-timing/parser.ts +97 -0
  576. package/src/record/gpu-pass-timing/session.ts +938 -0
  577. package/src/record/gpu-timing.ts +112 -39
  578. package/src/record/helpers.ts +0 -58
  579. package/src/record/main-pass-geometry.ts +324 -119
  580. package/src/record/main-pass-material.ts +103 -10
  581. package/src/record/main-pass-sprite-draws.ts +99 -103
  582. package/src/record/main-pass.ts +71 -15
  583. package/src/record/mesh-ssbo.ts +47 -36
  584. package/src/record/render-context.ts +136 -3
  585. package/src/record/shadow-pass.ts +83 -68
  586. package/src/record/skybox-post-pass.ts +20 -4
  587. package/src/record/typed-frame-graph.ts +1034 -43
  588. package/src/record/view-ubo.ts +72 -47
  589. package/src/reflection/filter.ts +81 -0
  590. package/src/reflection/gpu-table.ts +44 -0
  591. package/src/reflection/inspection.ts +67 -0
  592. package/src/reflection/projection.ts +476 -0
  593. package/src/reflection/record-owner.ts +1283 -0
  594. package/src/render-contract.ts +93 -10
  595. package/src/render-graph-primitives.ts +9 -4
  596. package/src/render-pipeline.ts +122 -2
  597. package/src/render-system-extract.ts +1041 -225
  598. package/src/render-system.ts +1310 -85
  599. package/src/renderer.ts +222 -0
  600. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
  601. package/src/scene/probe-blend-record.ts +54 -0
  602. package/src/scene/probe-blend.ts +813 -0
  603. package/src/scene/render-scene-types.ts +0 -7
  604. package/src/scene/render-scene.ts +942 -171
  605. package/src/scene/visibility/bounds.ts +57 -0
  606. package/src/scene/visibility/budget.ts +40 -0
  607. package/src/scene/visibility/facet.ts +400 -0
  608. package/src/scene/visibility/gpu-frame-timing.ts +101 -0
  609. package/src/scene/visibility/gpu-lod.ts +119 -0
  610. package/src/scene/visibility/inspection.ts +313 -0
  611. package/src/scene/visibility/lod-selector.ts +84 -0
  612. package/src/scene/visibility/occlusion-confidence.ts +478 -0
  613. package/src/scene/visibility/occlusion-pass.ts +165 -0
  614. package/src/scene/visibility/occlusion-query-pool.ts +178 -0
  615. package/src/scene/visibility/occlusion-runtime.ts +672 -0
  616. package/src/scene/visibility/types.ts +50 -0
  617. package/src/shadow-atlas.ts +5 -5
  618. package/src/ssao-buffers.ts +9 -2
  619. package/src/ssr/admission.ts +451 -0
  620. package/src/ssr/composition.ts +73 -0
  621. package/src/ssr/errors.ts +76 -0
  622. package/src/ssr/identity.ts +12 -0
  623. package/src/systems/skin-palette-allocator.ts +1 -1
  624. package/src/targets/contracts.ts +182 -0
  625. package/src/targets/graph-projection.ts +169 -0
  626. package/src/targets/material-source.ts +143 -0
  627. package/src/targets/owner.ts +214 -0
  628. package/src/targets/physical.ts +18 -0
  629. package/src/targets/readback.ts +153 -0
  630. package/src/temporal/frame-coordinator.ts +26 -0
  631. package/src/temporal/frame.ts +14 -1
  632. package/src/temporal/view.ts +11 -0
  633. package/src/tilemap-chunk-extract-system.ts +4 -4
  634. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
  635. package/src/typed-render-graph-primitives.ts +53 -3
  636. package/src/typed-shadow-passes.ts +46 -40
  637. package/src/volume/passes.ts +61 -58
  638. package/dist/.tsbuildinfo +0 -1
  639. package/dist/chunk-4XINDLAY.mjs.map +0 -1
  640. package/dist/chunk-CDTWTHZR.mjs.map +0 -1
  641. package/dist/chunk-M2MP4ZOU.mjs +0 -73
  642. package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
  643. package/dist/chunk-PCHBPYML.mjs.map +0 -1
  644. package/dist/chunk-TBQJOK2L.mjs.map +0 -1
  645. package/dist/chunk-VFPLTKCU.mjs.map +0 -1
@@ -0,0 +1,16 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { resolveReflectionFallbackTemporalReset } from '../temporal/frame-coordinator';
3
+
4
+ describe('fallback generation temporal boundary', () => {
5
+ it('resets only when a committed semantic generation changes', () => {
6
+ expect(resolveReflectionFallbackTemporalReset(4, 4)).toEqual({ reset: false });
7
+ expect(resolveReflectionFallbackTemporalReset(4, 5)).toEqual({
8
+ reset: true,
9
+ reason: 'reflection-fallback-generation',
10
+ });
11
+ });
12
+
13
+ it('does not create a temporal demand for an unavailable projection', () => {
14
+ expect(resolveReflectionFallbackTemporalReset(undefined, 4)).toEqual({ reset: false });
15
+ });
16
+ });
@@ -132,7 +132,7 @@ describe('TemporalView v1', () => {
132
132
  } as unknown as ExtractedLights;
133
133
  const buffer = {} as Parameters<typeof writeViewUbo>[1];
134
134
  const first = createTemporalView({ antialias: 'taa', width: 4, height: 4, frameIndex: 0 });
135
- writeViewUbo(queue, buffer, camera, light, lights, [], undefined, first);
135
+ writeViewUbo(queue, buffer, camera, light, lights, [], first);
136
136
  expect(Array.from(uploads[0]?.slice(212, 228) ?? [])).toEqual(new Array(16).fill(0));
137
137
 
138
138
  const previous = Float32Array.from({ length: 16 }, (_value, index) => index + 1);
@@ -143,10 +143,10 @@ describe('TemporalView v1', () => {
143
143
  frameIndex: 1,
144
144
  previousUnjitteredViewProjection: previous,
145
145
  });
146
- writeViewUbo(queue, buffer, camera, light, lights, [], undefined, second);
146
+ writeViewUbo(queue, buffer, camera, light, lights, [], second);
147
147
  expect(Array.from(uploads[1]?.slice(212, 228) ?? [])).toEqual(Array.from(previous));
148
148
 
149
- writeViewUbo(queue, buffer, camera, light, lights, [], undefined, second);
149
+ writeViewUbo(queue, buffer, camera, light, lights, [], second);
150
150
  expect(Array.from(uploads[2]?.slice(212, 228) ?? [])).toEqual(Array.from(previous));
151
151
  });
152
152
  });
@@ -13,6 +13,10 @@ const hdrpFalseKey =
13
13
  'CLUSTER_FORWARD_AVAILABLE=true+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=false+VERTEX_COLOR_AVAILABLE=false';
14
14
  const hdrpTrueKey =
15
15
  'CLUSTER_FORWARD_AVAILABLE=true+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=true+VERTEX_COLOR_AVAILABLE=false';
16
+ const probeFalseKey =
17
+ 'CLUSTER_FORWARD_AVAILABLE=false+PROBE_BLEND_AVAILABLE=true+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=false+VERTEX_COLOR_AVAILABLE=false';
18
+ const probeTrueKey =
19
+ 'CLUSTER_FORWARD_AVAILABLE=false+PROBE_BLEND_AVAILABLE=true+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=true+VERTEX_COLOR_AVAILABLE=false';
16
20
 
17
21
  function standardEntry(
18
22
  variants: readonly MaterialShaderManifestEntry['variants'][number][],
@@ -52,6 +56,33 @@ function hdrpVariant(definesKey: string, transmission: boolean) {
52
56
  };
53
57
  }
54
58
 
59
+ function probeTransmissionVariant(definesKey: string, transmission: boolean) {
60
+ const base = transmissionVariant(definesKey, transmission);
61
+ return {
62
+ ...base,
63
+ definesKey,
64
+ defines: { ...base.defines, PROBE_BLEND_AVAILABLE: true },
65
+ };
66
+ }
67
+
68
+ function capabilityTransmissionVariant(
69
+ definesKey: string,
70
+ transmission: boolean,
71
+ extendedLighting: boolean,
72
+ ) {
73
+ const base = transmissionVariant(definesKey, transmission);
74
+ return {
75
+ ...base,
76
+ definesKey,
77
+ defines: {
78
+ ...base.defines,
79
+ EXTENDED_LIGHTING_AVAILABLE: extendedLighting,
80
+ PROJECTOR_AVAILABLE: true,
81
+ },
82
+ composedWgsl: `standard-${extendedLighting ? 'extended' : 'fallback'}-${transmission}`,
83
+ };
84
+ }
85
+
55
86
  describe('Standard transmission exact-key prewarm selection', () => {
56
87
  it('returns both declared variants through exact manifest lookup', () => {
57
88
  const entry = standardEntry([
@@ -74,6 +105,44 @@ describe('Standard transmission exact-key prewarm selection', () => {
74
105
  'manifest row is missing',
75
106
  );
76
107
  });
108
+
109
+ it('keeps object-level probe variants out of the boot prewarm selection', () => {
110
+ const entry = standardEntry([
111
+ probeTransmissionVariant(probeFalseKey, false),
112
+ transmissionVariant(falseKey, false),
113
+ probeTransmissionVariant(probeTrueKey, true),
114
+ transmissionVariant(trueKey, true),
115
+ ]);
116
+ expect(
117
+ selectStandardPbrTransmissionPrewarmVariants(entry, true).map(
118
+ (variant) => variant.definesKey,
119
+ ),
120
+ ).toEqual([falseKey, trueKey]);
121
+ });
122
+
123
+ it('selects the prewarm pair for the admitted extended-lighting capability', () => {
124
+ const fallbackFalseKey = `${falseKey}+EXTENDED_LIGHTING_AVAILABLE=false+PROJECTOR_AVAILABLE=true`;
125
+ const fallbackTrueKey = `${trueKey}+EXTENDED_LIGHTING_AVAILABLE=false+PROJECTOR_AVAILABLE=true`;
126
+ const extendedFalseKey = `${falseKey}+EXTENDED_LIGHTING_AVAILABLE=true+PROJECTOR_AVAILABLE=true`;
127
+ const extendedTrueKey = `${trueKey}+EXTENDED_LIGHTING_AVAILABLE=true+PROJECTOR_AVAILABLE=true`;
128
+ const entry = standardEntry([
129
+ capabilityTransmissionVariant(fallbackFalseKey, false, false),
130
+ capabilityTransmissionVariant(fallbackTrueKey, true, false),
131
+ capabilityTransmissionVariant(extendedFalseKey, false, true),
132
+ capabilityTransmissionVariant(extendedTrueKey, true, true),
133
+ ]);
134
+
135
+ expect(
136
+ selectStandardPbrTransmissionPrewarmVariants(entry, true, true, true, false).map(
137
+ (variant) => variant.definesKey,
138
+ ),
139
+ ).toEqual([fallbackFalseKey, fallbackTrueKey]);
140
+ expect(
141
+ selectStandardPbrTransmissionPrewarmVariants(entry, true, true, true, true).map(
142
+ (variant) => variant.definesKey,
143
+ ),
144
+ ).toEqual([extendedFalseKey, extendedTrueKey]);
145
+ });
77
146
  });
78
147
 
79
148
  describe('HDRP PBR prewarm capability selection', () => {
@@ -1,17 +1,32 @@
1
1
  import { readFileSync } from 'node:fs';
2
+ import { mat4, vec3 } from '@forgeax/engine-math';
2
3
  import { RenderGraphBuilder } from '@forgeax/engine-render-graph';
3
4
  import type { RhiDevice } from '@forgeax/engine-rhi';
4
5
  import { rhi } from '@forgeax/engine-rhi-null';
5
6
  import { ok } from '@forgeax/engine-types';
6
7
  import { beforeAll, describe, expect, it } from 'vitest';
8
+ import { shouldExecuteStandardClusterMembershipPass } from '../pipeline/standard-lighting/graph';
9
+ import {
10
+ prepareStandardLighting,
11
+ type StandardLightFrame,
12
+ } from '../pipeline/standard-lighting/prepare';
13
+ import {
14
+ deriveStandardTopologyInput,
15
+ standardLightingTopologySignature,
16
+ } from '../pipeline/standard-lighting/topology';
17
+ import { selectStandardClusterTransport } from '../pipeline/standard-lighting/transport';
7
18
  import { standardPipeline } from '../pipeline/standard-pipeline';
8
19
  import { DEFAULT_STANDARD_PROFILE } from '../pipeline/standard-profile';
9
- import { isMotionBlurTemporalDemand } from '../record/typed-frame-graph';
20
+ import {
21
+ isMotionBlurTemporalDemand,
22
+ resolvePostProcessChainAdmission,
23
+ } from '../record/typed-frame-graph';
10
24
  import type {
11
25
  RenderPipeline,
12
26
  RenderPipelineFrame,
13
27
  RenderPipelineTopology,
14
28
  } from '../render-pipeline';
29
+ import { resolveOutputDither } from '../render-pipeline';
15
30
  import { standardTemporalPostOrder } from '../temporal/standard-scene-data';
16
31
 
17
32
  let device: RhiDevice;
@@ -39,8 +54,8 @@ function topology(
39
54
  },
40
55
  camera: { tonemap: 'aces-filmic', antialias: 'fxaa', bloom: 'on' },
41
56
  shadow: {
42
- mapSize: 1024,
43
- cascadeCount: 4,
57
+ directional: { mapSize: 1024, cascadeCount: 4 },
58
+ spotMapSize: 1024,
44
59
  pointCount: 1,
45
60
  pointFaceSize: 512,
46
61
  spotCount: 1,
@@ -57,13 +72,65 @@ function topology(
57
72
  };
58
73
  }
59
74
 
75
+ function zeroStandardLighting(caps: { compute: boolean; storageBuffer: boolean }, localCount = 1) {
76
+ const prepared = prepareStandardLighting({
77
+ directional: undefined,
78
+ local: Array.from({ length: localCount }, (_, index) => ({
79
+ kind: 'point' as const,
80
+ shadowed: false,
81
+ position: vec3.create(index, 0, -4),
82
+ range: 2,
83
+ })),
84
+ view: mat4.create(),
85
+ projection: mat4.create(),
86
+ near: 0.1,
87
+ far: 100,
88
+ grid: { x: 4, y: 3, z: 4 },
89
+ lightCount: DEFAULT_STANDARD_PROFILE.lightCount,
90
+ renderPath: 'forward',
91
+ });
92
+ if (!prepared.ok) throw prepared.error;
93
+ const transport = selectStandardClusterTransport(
94
+ { ...caps, membershipPipelineReady: caps.compute },
95
+ prepared.value,
96
+ );
97
+ if (!transport.ok) return transport;
98
+ return deriveStandardTopologyInput({
99
+ kind: 'clustered',
100
+ prepared: prepared.value,
101
+ transport: transport.value,
102
+ });
103
+ }
104
+
105
+ function noLocalStandardLighting() {
106
+ const prepared = prepareStandardLighting({
107
+ directional: undefined,
108
+ local: [],
109
+ view: mat4.create(),
110
+ projection: mat4.create(),
111
+ near: 0.1,
112
+ far: 100,
113
+ grid: { x: 4, y: 3, z: 4 },
114
+ lightCount: 1,
115
+ renderPath: 'forward',
116
+ });
117
+ if (!prepared.ok) throw prepared.error;
118
+ return deriveStandardTopologyInput({ kind: 'no-local-lights', prepared: prepared.value });
119
+ }
120
+
60
121
  function compile(pipeline: RenderPipeline, input: RenderPipelineTopology) {
61
122
  const graph = new RenderGraphBuilder<RenderPipelineFrame>();
123
+ const standardLighting = zeroStandardLighting({
124
+ compute: input.lane.compute,
125
+ storageBuffer: input.lane.storageBuffer,
126
+ });
127
+ if (!standardLighting.ok) return standardLighting;
62
128
  const importedHistory =
63
129
  input.camera.antialias === 'taa' ? createImportedHistory(graph) : undefined;
64
130
  const built = pipeline.build(
65
131
  {
66
132
  graph,
133
+ standardLighting: standardLighting.value,
67
134
  capabilities: { rgba16floatRenderable: true },
68
135
  ...(importedHistory === undefined ? {} : { taaHistory: importedHistory }),
69
136
  projectGpuDriven: () => ok(undefined),
@@ -78,6 +145,38 @@ function compile(pipeline: RenderPipeline, input: RenderPipelineTopology) {
78
145
  });
79
146
  }
80
147
 
148
+ function disabledDirectionalTopology(): RenderPipelineTopology {
149
+ return topology('forgeax::standard', {
150
+ shadow: {
151
+ directional: 'disabled',
152
+ pointCount: 0,
153
+ pointFaceSize: 512,
154
+ spotCount: 0,
155
+ } as unknown as RenderPipelineTopology['shadow'],
156
+ });
157
+ }
158
+
159
+ function disabledDirectionalVolumeTopology(lightKind: 'point' | 'spot'): RenderPipelineTopology {
160
+ return topology('forgeax::standard', {
161
+ shadow: {
162
+ directional: 'disabled',
163
+ spotMapSize: 1024,
164
+ pointCount: 0,
165
+ pointFaceSize: 512,
166
+ spotCount: lightKind === 'spot' ? 1 : 0,
167
+ },
168
+ volumetricFog: {
169
+ enabled: true,
170
+ lightKind,
171
+ lightEntity: 1,
172
+ format: 'rgba8unorm',
173
+ extent: { width: 8, height: 8, depth: 8 },
174
+ froxelExtent: { width: 16, height: 16, depth: 8 },
175
+ resolvedExtent: { width: 8, height: 8, depth: 1 },
176
+ },
177
+ });
178
+ }
179
+
81
180
  function createImportedHistory(graph: RenderGraphBuilder<RenderPipelineFrame>) {
82
181
  const target = (label: string) => {
83
182
  const texture = graph.importTexture(
@@ -104,6 +203,248 @@ function createImportedHistory(graph: RenderGraphBuilder<RenderPipelineFrame>) {
104
203
  }
105
204
 
106
205
  describe('typed built-in pipeline topology', () => {
206
+ it('defaults final output dither on and accepts an asset-level opt-out', () => {
207
+ expect(resolveOutputDither(undefined)).toBe(true);
208
+ expect(resolveOutputDither({ outputDither: true })).toBe(true);
209
+ expect(resolveOutputDither({ outputDither: false })).toBe(false);
210
+ });
211
+
212
+ it('omits every Directional shadow graph resource and pass when disabled', () => {
213
+ const compiled = compile(standardPipeline, disabledDirectionalTopology());
214
+ expect(compiled.ok).toBe(true);
215
+ if (!compiled.ok) return;
216
+ const info = compiled.value.inspect();
217
+ expect(info.resources.some((resource) => resource.label === 'directional-shadow-depth')).toBe(
218
+ false,
219
+ );
220
+ expect(
221
+ info.passes.some(
222
+ (pass) =>
223
+ pass.name.startsWith('shadowCascade') || pass.name === 'directional-shadow-observation',
224
+ ),
225
+ ).toBe(false);
226
+ const main = info.passes.find((pass) => pass.name === 'main');
227
+ expect(main?.accesses.some((access) => access.resource === 'directional-shadow-depth')).toBe(
228
+ false,
229
+ );
230
+ });
231
+
232
+ it('falsifies a test-only shadow-off topology that still builds a Directional pass', () => {
233
+ const compiled = compile(standardPipeline, disabledDirectionalTopology());
234
+ expect(compiled.ok).toBe(true);
235
+ if (!compiled.ok) return;
236
+ const count = compiled.value
237
+ .inspect()
238
+ .passes.filter(
239
+ (pass) =>
240
+ pass.name.startsWith('shadowCascade') || pass.name === 'directional-shadow-observation',
241
+ ).length;
242
+ const expected = process.env.FALSIFY === 'shadow-off-still-builds-pass' ? 1 : 0;
243
+ expect(count).toBe(expected);
244
+ });
245
+
246
+ it.each([
247
+ 'point',
248
+ 'spot',
249
+ ] as const)('keeps %s volumetric fog graphable when directional shadows are disabled', (lightKind) => {
250
+ const compiled = compile(standardPipeline, disabledDirectionalVolumeTopology(lightKind));
251
+ expect(compiled.ok).toBe(true);
252
+ if (!compiled.ok) return;
253
+ const info = compiled.value.inspect();
254
+ expect(info.resources.some((resource) => resource.label === 'directional-shadow-depth')).toBe(
255
+ false,
256
+ );
257
+ expect(info.passes.some((pass) => pass.name === 'volume-inject')).toBe(true);
258
+ expect(
259
+ info.passes.some(
260
+ (pass) =>
261
+ pass.name.startsWith('shadowCascade') || pass.name === 'directional-shadow-observation',
262
+ ),
263
+ ).toBe(false);
264
+ });
265
+
266
+ it('derives topology only from prepared transport facts', () => {
267
+ const frame: StandardLightFrame = {
268
+ directional: undefined,
269
+ local: [{ kind: 'point', shadowed: false, position: vec3.create(0, 0, -4), range: 2 }],
270
+ view: mat4.lookAt(mat4.create(), [0, 0, 0], [0, 0, -1], [0, 1, 0]),
271
+ projection: mat4.perspective(mat4.create(), Math.PI / 3, 1, 0.1, 100),
272
+ near: 0.1,
273
+ far: 100,
274
+ grid: { x: 4, y: 3, z: 4 },
275
+ lightCount: 32,
276
+ renderPath: 'forward',
277
+ };
278
+ const prepared = prepareStandardLighting(frame);
279
+ expect(prepared.ok).toBe(true);
280
+ if (!prepared.ok) return;
281
+ const transport = selectStandardClusterTransport(
282
+ { compute: true, storageBuffer: true, membershipPipelineReady: true },
283
+ prepared.value,
284
+ );
285
+ expect(transport.ok).toBe(true);
286
+ if (!transport.ok) return;
287
+ const derived = deriveStandardTopologyInput({
288
+ prepared: prepared.value,
289
+ kind: 'clustered',
290
+ transport: transport.value,
291
+ });
292
+ expect(derived.ok).toBe(true);
293
+ if (!derived.ok) return;
294
+ expect(derived.value.kind).toBe('clustered');
295
+ if (derived.value.kind !== 'clustered') return;
296
+ expect(derived.value.transport.kind).toBe('compute-storage');
297
+ expect(derived.value.prepared).toBe(prepared.value);
298
+ });
299
+
300
+ it('keeps graph identity stable for per-frame light movement and count changes', () => {
301
+ const make = (localCount: number) => {
302
+ const prepared = prepareStandardLighting({
303
+ directional: undefined,
304
+ local: Array.from({ length: localCount }, (_, index) => ({
305
+ kind: index % 2 === 0 ? ('point' as const) : ('spot' as const),
306
+ shadowed: false,
307
+ position: vec3.create(index, 0, -4),
308
+ range: 2,
309
+ })),
310
+ view: mat4.create(),
311
+ projection: mat4.create(),
312
+ near: 0.1,
313
+ far: 100,
314
+ grid: { x: 4, y: 3, z: 4 },
315
+ lightCount: 32,
316
+ renderPath: 'forward',
317
+ });
318
+ if (!prepared.ok) throw prepared.error;
319
+ const transport = selectStandardClusterTransport(
320
+ { compute: true, storageBuffer: true, membershipPipelineReady: true },
321
+ prepared.value,
322
+ );
323
+ if (!transport.ok) throw transport.error;
324
+ const input = deriveStandardTopologyInput({
325
+ kind: 'clustered',
326
+ prepared: prepared.value,
327
+ transport: transport.value,
328
+ });
329
+ if (!input.ok) throw input.error;
330
+ return input.value;
331
+ };
332
+ expect(standardLightingTopologySignature(make(1))).toBe(
333
+ standardLightingTopologySignature(make(2)),
334
+ );
335
+ const empty = noLocalStandardLighting();
336
+ expect(empty.ok).toBe(true);
337
+ if (!empty.ok) return;
338
+ expect(standardLightingTopologySignature(make(1))).not.toBe(
339
+ standardLightingTopologySignature(empty.value),
340
+ );
341
+ expect(standardLightingTopologySignature(undefined)).not.toBe(
342
+ standardLightingTopologySignature(empty.value),
343
+ );
344
+ });
345
+
346
+ it('keeps the clustered graph and ABI stable across local-light 1 to 0 to 1', () => {
347
+ const capabilities = { compute: true, storageBuffer: true };
348
+ const one = zeroStandardLighting(capabilities, 1);
349
+ const zero = zeroStandardLighting(capabilities, 0);
350
+ const oneAgain = zeroStandardLighting(capabilities, 1);
351
+ expect(one.ok && zero.ok && oneAgain.ok).toBe(true);
352
+ if (!one.ok || !zero.ok || !oneAgain.ok) return;
353
+ expect(one.value.kind).toBe('clustered');
354
+ expect(zero.value.kind).toBe('clustered');
355
+ expect(oneAgain.value.kind).toBe('clustered');
356
+ expect(standardLightingTopologySignature(zero.value)).toBe(
357
+ standardLightingTopologySignature(one.value),
358
+ );
359
+ expect(standardLightingTopologySignature(oneAgain.value)).toBe(
360
+ standardLightingTopologySignature(one.value),
361
+ );
362
+
363
+ const graph = new RenderGraphBuilder<RenderPipelineFrame>();
364
+ const built = standardPipeline.build(
365
+ {
366
+ graph,
367
+ standardLighting: zero.value,
368
+ capabilities: { rgba16floatRenderable: true },
369
+ projectGpuDriven: () => ok(undefined),
370
+ contributeFeatures: () => ok(undefined),
371
+ },
372
+ topology('forgeax::standard', {
373
+ shadow: {
374
+ directional: 'disabled',
375
+ pointCount: 0,
376
+ pointFaceSize: 512,
377
+ spotCount: 0,
378
+ } as unknown as RenderPipelineTopology['shadow'],
379
+ camera: { tonemap: 'none', antialias: 'none', bloom: 'off' },
380
+ }),
381
+ );
382
+ expect(built.ok).toBe(true);
383
+ if (!built.ok) return;
384
+ const compiled = graph.compile({ device, surfaceSize: { width: 800, height: 600 } });
385
+ expect(compiled.ok).toBe(true);
386
+ if (!compiled.ok) return;
387
+ const info = compiled.value.inspect();
388
+ expect(info.passes.map((pass) => pass.name)).toContain('cluster-membership-producer');
389
+ expect(info.resources.map((resource) => resource.label)).toContain('hdrp-light-data');
390
+ });
391
+
392
+ it('evaluates Cluster membership from the current frame, not graph-build light count', () => {
393
+ const one = zeroStandardLighting({ compute: true, storageBuffer: true }, 1);
394
+ const zero = zeroStandardLighting({ compute: true, storageBuffer: true }, 0);
395
+ expect(one.ok && zero.ok).toBe(true);
396
+ if (!one.ok || !zero.ok) return;
397
+ const asFrame = (standardLighting: typeof one.value) =>
398
+ ({ standardLighting }) as unknown as RenderPipelineFrame;
399
+ expect(shouldExecuteStandardClusterMembershipPass(asFrame(zero.value))).toBe(false);
400
+ expect(shouldExecuteStandardClusterMembershipPass(asFrame(one.value))).toBe(true);
401
+ expect(shouldExecuteStandardClusterMembershipPass(asFrame(zero.value))).toBe(false);
402
+ });
403
+
404
+ it('rejects raw capability and light data at the topology adapter boundary', () => {
405
+ const empty = zeroStandardLighting({ compute: true, storageBuffer: true });
406
+ expect(empty.ok).toBe(true);
407
+ if (!empty.ok) return;
408
+ expect(empty.value.kind).toBe('clustered');
409
+ if (empty.value.kind !== 'clustered') return;
410
+ const derived = deriveStandardTopologyInput({
411
+ kind: 'clustered',
412
+ prepared: empty.value.prepared,
413
+ transport: empty.value.transport,
414
+ lights: [],
415
+ } as unknown as Parameters<typeof deriveStandardTopologyInput>[0]);
416
+ expect(derived.ok).toBe(false);
417
+ if (derived.ok) return;
418
+ expect(derived.error.code).toBe('topology-input-invalid');
419
+ });
420
+
421
+ it('accepts an explicit no-local topology without allocating Cluster resources', () => {
422
+ const standardLighting = noLocalStandardLighting();
423
+ expect(standardLighting.ok).toBe(true);
424
+ if (!standardLighting.ok) return;
425
+ const graph = new RenderGraphBuilder<RenderPipelineFrame>();
426
+ const built = standardPipeline.build(
427
+ {
428
+ graph,
429
+ standardLighting: standardLighting.value,
430
+ capabilities: { rgba16floatRenderable: false },
431
+ projectGpuDriven: () => ok(undefined),
432
+ contributeFeatures: () => ok(undefined),
433
+ },
434
+ topology('forgeax::standard', {
435
+ lane: { compute: false, storageBuffer: false, multisample: false, maxColorAttachments: 4 },
436
+ camera: { tonemap: 'none', antialias: 'none', bloom: 'off' },
437
+ }),
438
+ );
439
+ expect(built.ok).toBe(true);
440
+ if (!built.ok) return;
441
+ const compiled = graph.compile({ device, surfaceSize: { width: 800, height: 600 } });
442
+ expect(compiled.ok).toBe(true);
443
+ if (!compiled.ok) return;
444
+ const info = compiled.value.inspect();
445
+ expect(info.passes.map((pass) => pass.name)).not.toContain('cluster-membership-producer');
446
+ expect(info.resources.map((resource) => resource.label)).not.toContain('hdrp-light-data');
447
+ });
107
448
  it('declares explicit output target domain and avoids alternate sRGB views', () => {
108
449
  const source = readFileSync(new URL('../render-pipeline.ts', import.meta.url), 'utf8');
109
450
  const postChainSource = readFileSync(
@@ -116,6 +457,25 @@ describe('typed built-in pipeline topology', () => {
116
457
  expect(source).not.toContain('viewFormats: [topology.surface.viewFormat]');
117
458
  });
118
459
 
460
+ it('forwards the output dither override into the fullscreen UBO write', () => {
461
+ const typedSource = readFileSync(
462
+ new URL('../typed-render-graph-primitives.ts', import.meta.url),
463
+ 'utf8',
464
+ );
465
+ const dispatcherSource = readFileSync(
466
+ new URL('../render-graph-primitives.ts', import.meta.url),
467
+ 'utf8',
468
+ );
469
+ expect(typedSource).toContain(
470
+ 'paramsOverride: options.paramsTransform(frame.postProcessParams.get(options.shader))',
471
+ );
472
+ expect(dispatcherSource).toContain('paramsOverride?: Uint8Array');
473
+ expect(dispatcherSource).toContain(
474
+ 'const data = paramsOverride ?? ctx.postProcessParams.get(shader);',
475
+ );
476
+ expect(dispatcherSource).toContain('input.paramsOverride,');
477
+ });
478
+
119
479
  it('declares stable JSON-safe output and observation inspection facts', () => {
120
480
  const source = readFileSync(new URL('../render-contract.ts', import.meta.url), 'utf8');
121
481
  for (const field of [
@@ -138,7 +498,7 @@ describe('typed built-in pipeline topology', () => {
138
498
  const compiled = compile(
139
499
  standardPipeline,
140
500
  topology('forgeax::standard', {
141
- standardProfile: { ...DEFAULT_STANDARD_PROFILE, lighting: 'clustered', ssao: true },
501
+ standardProfile: { ...DEFAULT_STANDARD_PROFILE, renderPath: 'deferred', ssao: true },
142
502
  }),
143
503
  );
144
504
  expect(compiled.ok).toBe(true);
@@ -147,6 +507,7 @@ describe('typed built-in pipeline topology', () => {
147
507
  const names = info.passes.map((pass) => pass.name);
148
508
  const ordered = [
149
509
  'cluster-membership-producer',
510
+ 'directional-shadow-observation',
150
511
  'g-buffer',
151
512
  'ssao-calc',
152
513
  'ssao-blur',
@@ -162,6 +523,8 @@ describe('typed built-in pipeline topology', () => {
162
523
  }
163
524
  expect(names.filter((name) => name.startsWith('point-shadow-'))).toHaveLength(6);
164
525
  expect(names.filter((name) => name.startsWith('shadowCascade'))).toHaveLength(4);
526
+ expect(names).toContain('directional-shadow-observation');
527
+ expect(names).toContain('linear-hdr-observation');
165
528
 
166
529
  const membership = info.passes.find((pass) => pass.name === 'cluster-membership-producer');
167
530
  expect(membership?.kind).toBe('compute');
@@ -185,11 +548,11 @@ describe('typed built-in pipeline topology', () => {
185
548
  const compiled = compile(
186
549
  standardPipeline,
187
550
  topology('forgeax::standard', {
188
- standardProfile: { ...DEFAULT_STANDARD_PROFILE, lighting: 'clustered' },
551
+ standardProfile: { ...DEFAULT_STANDARD_PROFILE, renderPath: 'deferred' },
189
552
  config: { ssao: { enabled: false } },
190
553
  lane: {
191
554
  compute: false,
192
- storageBuffer: false,
555
+ storageBuffer: true,
193
556
  multisample: false,
194
557
  maxColorAttachments: 8,
195
558
  },
@@ -245,7 +608,23 @@ describe('typed built-in pipeline topology', () => {
245
608
  expect(effect1?.dependencies).toContain('post-effect-copy-1');
246
609
  });
247
610
 
248
- it('removes unsupported MSAA and composite post work on the fallback lane', () => {
611
+ it('admits the fullscreen post-effect chain atomically', () => {
612
+ const visited: string[] = [];
613
+ const pending = resolvePostProcessChainAdmission(['example::a', 'example::b'], (identity) => {
614
+ visited.push(identity);
615
+ return identity === 'example::a';
616
+ });
617
+ expect(pending).toEqual({ admitted: [], pending: true });
618
+ expect(visited).toEqual(['example::a', 'example::b']);
619
+
620
+ const ready = resolvePostProcessChainAdmission(['example::a', 'example::b'], () => true);
621
+ expect(ready).toEqual({
622
+ admitted: ['example::a', 'example::b'],
623
+ pending: false,
624
+ });
625
+ });
626
+
627
+ it('removes unsupported MSAA while retaining the CPU storage lane', () => {
249
628
  const compiled = compile(
250
629
  standardPipeline,
251
630
  topology('forgeax::standard', {
@@ -253,7 +632,7 @@ describe('typed built-in pipeline topology', () => {
253
632
  config: { postEffects: ['example::a'] },
254
633
  lane: {
255
634
  compute: false,
256
- storageBuffer: false,
635
+ storageBuffer: true,
257
636
  multisample: false,
258
637
  maxColorAttachments: 4,
259
638
  },
@@ -263,7 +642,7 @@ describe('typed built-in pipeline topology', () => {
263
642
  if (!compiled.ok) return;
264
643
  const info = compiled.value.inspect();
265
644
  expect(info.resources.some((resource) => resource.label.includes('msaa'))).toBe(false);
266
- expect(info.passes.some((pass) => pass.name.startsWith('post-effect-'))).toBe(false);
645
+ expect(info.passes.some((pass) => pass.name.startsWith('post-effect-'))).toBe(true);
267
646
  });
268
647
 
269
648
  it('declares one TAA producer and resolve for TAA demand', () => {
@@ -299,9 +678,12 @@ describe('typed built-in pipeline topology', () => {
299
678
 
300
679
  it('fails closed when TAA history imports are missing', () => {
301
680
  const graph = new RenderGraphBuilder<RenderPipelineFrame>();
681
+ const standardLighting = zeroStandardLighting({ compute: true, storageBuffer: true });
682
+ if (!standardLighting.ok) throw standardLighting.error;
302
683
  const built = standardPipeline.build(
303
684
  {
304
685
  graph,
686
+ standardLighting: standardLighting.value,
305
687
  capabilities: { rgba16floatRenderable: true },
306
688
  projectGpuDriven: () => ok(undefined),
307
689
  contributeFeatures: () => ok(undefined),
@@ -326,7 +708,7 @@ describe('typed built-in pipeline topology', () => {
326
708
  temporal: { taa: true, motionBlur: true },
327
709
  lane: {
328
710
  compute: false,
329
- storageBuffer: false,
711
+ storageBuffer: true,
330
712
  multisample: false,
331
713
  maxColorAttachments: 4,
332
714
  },
@@ -412,11 +794,11 @@ describe('typed built-in pipeline topology', () => {
412
794
  ).toHaveLength(0);
413
795
  });
414
796
 
415
- it('returns a structured HDRP capability refusal before graph compilation', () => {
797
+ it('keeps deferred attachment admission independent from the Cluster transport', () => {
416
798
  const built = compile(
417
799
  standardPipeline,
418
800
  topology('forgeax::standard', {
419
- standardProfile: { ...DEFAULT_STANDARD_PROFILE, lighting: 'clustered' },
801
+ standardProfile: { ...DEFAULT_STANDARD_PROFILE, renderPath: 'deferred' },
420
802
  lane: {
421
803
  compute: true,
422
804
  storageBuffer: true,
@@ -425,8 +807,7 @@ describe('typed built-in pipeline topology', () => {
425
807
  },
426
808
  }),
427
809
  );
428
- expect(built.ok).toBe(false);
429
- if (!built.ok) expect(built.error.code).toBe('hdrp-deferred-caps-insufficient');
810
+ expect(built.ok).toBe(true);
430
811
  });
431
812
  });
432
813
 
@@ -40,10 +40,10 @@ describe('urp render feature targets', () => {
40
40
  });
41
41
  });
42
42
 
43
- it('keeps the surface target for non-storage-buffer LDR frames', () => {
43
+ it('publishes a float target for non-storage-buffer LDR frames', () => {
44
44
  expect(targets('none', 'none', false)?.[0]).toMatchObject({
45
45
  kind: 'scene-color',
46
- format: 'bgra8unorm-srgb',
46
+ format: 'rgba16float',
47
47
  sampleCount: 1,
48
48
  });
49
49
  });