@forgeax/engine-render 0.1.21 → 0.1.24

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 (584) hide show
  1. package/README.md +281 -38
  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/bundler-contract.d.ts +9 -0
  5. package/dist/assembly/bundler-contract.d.ts.map +1 -0
  6. package/dist/assembly/device-feature-admission.d.ts +8 -0
  7. package/dist/assembly/device-feature-admission.d.ts.map +1 -1
  8. package/dist/assembly/extended-lighting-fallback.d.ts +13 -0
  9. package/dist/assembly/extended-lighting-fallback.d.ts.map +1 -0
  10. package/dist/assembly/factory.d.ts +7 -235
  11. package/dist/assembly/factory.d.ts.map +1 -1
  12. package/dist/assembly/host-contract.d.ts +10 -0
  13. package/dist/assembly/host-contract.d.ts.map +1 -1
  14. package/dist/assembly/material/assembly.d.ts +3 -2
  15. package/dist/assembly/material/assembly.d.ts.map +1 -1
  16. package/dist/assembly/material/standard-layer-projection.d.ts +10 -0
  17. package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -0
  18. package/dist/assembly/material-shader-policy.d.ts +168 -0
  19. package/dist/assembly/material-shader-policy.d.ts.map +1 -0
  20. package/dist/assembly/material-shader-prewarm.d.ts +21 -0
  21. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -0
  22. package/dist/assembly/mesh-ssbo-grow.d.ts +88 -0
  23. package/dist/assembly/mesh-ssbo-grow.d.ts.map +1 -0
  24. package/dist/assembly/recovery/device-loss-fanout.d.ts +14 -0
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -0
  26. package/dist/assembly/recovery/generation.d.ts +46 -0
  27. package/dist/assembly/recovery/generation.d.ts.map +1 -0
  28. package/dist/assembly/recovery/recovery-attempt.d.ts +63 -0
  29. package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -0
  30. package/dist/assembly/recovery/renderer-recover.d.ts +115 -0
  31. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -0
  32. package/dist/assembly/renderer-facade.d.ts +10 -0
  33. package/dist/assembly/renderer-facade.d.ts.map +1 -0
  34. package/dist/assembly/renderer-frame-transaction.d.ts +17 -0
  35. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  36. package/dist/assembly/renderer-helpers.d.ts +19 -0
  37. package/dist/assembly/renderer-helpers.d.ts.map +1 -0
  38. package/dist/assembly/renderer-lifecycle.d.ts +34 -0
  39. package/dist/assembly/renderer-lifecycle.d.ts.map +1 -1
  40. package/dist/assembly/shader-prewarm-policy.d.ts +15 -0
  41. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -0
  42. package/dist/assembly/webgpu-ready-contract.d.ts +9 -0
  43. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -0
  44. package/dist/assembly/webgpu-ready.d.ts +55 -0
  45. package/dist/assembly/webgpu-ready.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-renderer.d.ts +152 -0
  47. package/dist/assembly/webgpu-renderer.d.ts.map +1 -0
  48. package/dist/authoring.mjs +1 -1
  49. package/dist/{chunk-PCHBPYML.mjs → chunk-GE3SDD72.mjs} +37 -5
  50. package/dist/chunk-GE3SDD72.mjs.map +1 -0
  51. package/dist/chunk-KZFTK6DO.mjs +1191 -0
  52. package/dist/chunk-KZFTK6DO.mjs.map +1 -0
  53. package/dist/{chunk-FS2KNUQH.mjs → chunk-Q752SHI5.mjs} +332 -568
  54. package/dist/chunk-Q752SHI5.mjs.map +1 -0
  55. package/dist/{chunk-6OPXDQ2E.mjs → chunk-RR5L4SRS.mjs} +33 -294
  56. package/dist/chunk-RR5L4SRS.mjs.map +1 -0
  57. package/dist/chunk-TFH5I7JJ.mjs +296 -0
  58. package/dist/chunk-TFH5I7JJ.mjs.map +1 -0
  59. package/dist/chunk-UQYS7FRM.mjs +1003 -0
  60. package/dist/chunk-UQYS7FRM.mjs.map +1 -0
  61. package/dist/chunk-YKB5DQV7.mjs +345 -0
  62. package/dist/chunk-YKB5DQV7.mjs.map +1 -0
  63. package/dist/{chunk-5YADUCA7.mjs → chunk-YRUYGA4A.mjs} +1189 -1217
  64. package/dist/chunk-YRUYGA4A.mjs.map +1 -0
  65. package/dist/chunk-Z3YYH2MB.mjs +5082 -0
  66. package/dist/chunk-Z3YYH2MB.mjs.map +1 -0
  67. package/dist/cluster-binner.d.ts +5 -0
  68. package/dist/cluster-binner.d.ts.map +1 -1
  69. package/dist/components/index.d.ts +3 -0
  70. package/dist/components/index.d.ts.map +1 -1
  71. package/dist/components/light-helpers.d.ts +4 -0
  72. package/dist/components/light-helpers.d.ts.map +1 -1
  73. package/dist/components/light-probe.d.ts +9 -0
  74. package/dist/components/light-probe.d.ts.map +1 -0
  75. package/dist/components/rect-area-light.d.ts +12 -0
  76. package/dist/components/rect-area-light.d.ts.map +1 -0
  77. package/dist/components/scene-instance.d.ts +4 -0
  78. package/dist/components/scene-instance.d.ts.map +1 -1
  79. package/dist/components/spot-light.d.ts +3 -0
  80. package/dist/components/spot-light.d.ts.map +1 -1
  81. package/dist/construct-renderer.mjs +27276 -23232
  82. package/dist/construct-renderer.mjs.map +1 -1
  83. package/dist/device/device-scope.d.ts +2 -0
  84. package/dist/device/device-scope.d.ts.map +1 -1
  85. package/dist/device/gpu-residency.d.ts +32 -5
  86. package/dist/device/gpu-residency.d.ts.map +1 -1
  87. package/dist/device/lifecycle-transaction.d.ts +2 -0
  88. package/dist/device/lifecycle-transaction.d.ts.map +1 -0
  89. package/dist/environment/frame.d.ts +5 -0
  90. package/dist/environment/frame.d.ts.map +1 -1
  91. package/dist/environment/inspection.d.ts +7 -0
  92. package/dist/environment/inspection.d.ts.map +1 -1
  93. package/dist/environment/lifecycle.d.ts +20 -2
  94. package/dist/environment/lifecycle.d.ts.map +1 -1
  95. package/dist/errors/gpu-driven.d.ts +26 -0
  96. package/dist/errors/gpu-driven.d.ts.map +1 -0
  97. package/dist/errors/index.d.ts +1 -0
  98. package/dist/errors/index.d.ts.map +1 -1
  99. package/dist/errors/recover.d.ts +67 -3
  100. package/dist/errors/recover.d.ts.map +1 -1
  101. package/dist/errors/render.d.ts +39 -1
  102. package/dist/errors/render.d.ts.map +1 -1
  103. package/dist/extract/contracts.d.ts +899 -0
  104. package/dist/extract/contracts.d.ts.map +1 -0
  105. package/dist/extract/gpu-driven.d.ts +50 -0
  106. package/dist/extract/gpu-driven.d.ts.map +1 -0
  107. package/dist/extract/visibility.d.ts.map +1 -1
  108. package/dist/features/host.d.ts +2 -0
  109. package/dist/features/host.d.ts.map +1 -1
  110. package/dist/features/prepared-gpu-work.d.ts +3 -0
  111. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  112. package/dist/features/prepared-graphics-store.d.ts +2 -0
  113. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  114. package/dist/gpu-driven/batch-topology.d.ts +34 -0
  115. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  116. package/dist/gpu-driven/prepared-draw.d.ts +63 -0
  117. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
  118. package/dist/gpu-driven/production-raster.d.ts +126 -2
  119. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  120. package/dist/gpu-driven/view-gpu.d.ts +64 -1
  121. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  122. package/dist/gpu-scene-schema.d.ts +14 -0
  123. package/dist/gpu-scene-schema.d.ts.map +1 -1
  124. package/dist/gpu-scene.d.ts +9 -1
  125. package/dist/gpu-scene.d.ts.map +1 -1
  126. package/dist/gpu-usage.d.ts +0 -1
  127. package/dist/gpu-usage.d.ts.map +1 -1
  128. package/dist/hdrp-buffers.d.ts +3 -3
  129. package/dist/hdrp-buffers.d.ts.map +1 -1
  130. package/dist/ibl/IblPipelineCache.d.ts +7 -6
  131. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  132. package/dist/ibl/skylight-bind-group.d.ts +7 -1
  133. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  134. package/dist/index.d.ts +13 -2
  135. package/dist/index.d.ts.map +1 -1
  136. package/dist/index.mjs +90 -5
  137. package/dist/index.mjs.map +1 -1
  138. package/dist/inspection-types.d.ts +163 -1
  139. package/dist/inspection-types.d.ts.map +1 -1
  140. package/dist/internal.d.ts +9 -0
  141. package/dist/internal.d.ts.map +1 -1
  142. package/dist/internal.mjs +23 -2
  143. package/dist/internal.mjs.map +1 -1
  144. package/dist/light-buffer-layout.d.ts +60 -148
  145. package/dist/light-buffer-layout.d.ts.map +1 -1
  146. package/dist/materials.d.ts +34 -10
  147. package/dist/materials.d.ts.map +1 -1
  148. package/dist/mesh-material-bindings.d.ts +56 -0
  149. package/dist/mesh-material-bindings.d.ts.map +1 -1
  150. package/dist/occlusion-proxy.d.ts +4 -0
  151. package/dist/occlusion-proxy.d.ts.map +1 -0
  152. package/dist/pbr-pipeline.d.ts +58 -21
  153. package/dist/pbr-pipeline.d.ts.map +1 -1
  154. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  155. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -1
  156. package/dist/pipeline/standard-lighting/light-frame.d.ts +3 -3
  157. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -1
  158. package/dist/pipeline/standard-lighting/topology.d.ts +1 -1
  159. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -1
  160. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -1
  161. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  162. package/dist/pipeline-builder.d.ts +2 -0
  163. package/dist/pipeline-builder.d.ts.map +1 -1
  164. package/dist/pipeline-spec.d.ts +1 -1
  165. package/dist/pipeline-spec.d.ts.map +1 -1
  166. package/dist/plugin.d.ts.map +1 -1
  167. package/dist/points-lines/prepare.d.ts +3 -0
  168. package/dist/points-lines/prepare.d.ts.map +1 -1
  169. package/dist/points-lines/standard-owner.d.ts +33 -0
  170. package/dist/points-lines/standard-owner.d.ts.map +1 -0
  171. package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
  172. package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
  173. package/dist/prepare/extended-lighting/resources.d.ts +72 -0
  174. package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
  175. package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
  176. package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
  177. package/dist/prepare/extended-lighting/state.d.ts +24 -0
  178. package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
  179. package/dist/record/frame-lighting.d.ts +8 -6
  180. package/dist/record/frame-lighting.d.ts.map +1 -1
  181. package/dist/record/frame-snapshot.d.ts +55 -10
  182. package/dist/record/frame-snapshot.d.ts.map +1 -1
  183. package/dist/record/frame-targets.d.ts.map +1 -1
  184. package/dist/record/frame.d.ts +21 -5
  185. package/dist/record/frame.d.ts.map +1 -1
  186. package/dist/record/gpu-timing.d.ts +19 -7
  187. package/dist/record/gpu-timing.d.ts.map +1 -1
  188. package/dist/record/helpers.d.ts +0 -20
  189. package/dist/record/helpers.d.ts.map +1 -1
  190. package/dist/record/main-pass-geometry.d.ts +20 -2
  191. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  192. package/dist/record/main-pass-material.d.ts +10 -18
  193. package/dist/record/main-pass-material.d.ts.map +1 -1
  194. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  195. package/dist/record/main-pass.d.ts.map +1 -1
  196. package/dist/record/mesh-ssbo.d.ts +11 -3
  197. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  198. package/dist/record/recovery-pipeline.d.ts +30 -0
  199. package/dist/record/recovery-pipeline.d.ts.map +1 -0
  200. package/dist/record/render-context.d.ts +82 -9
  201. package/dist/record/render-context.d.ts.map +1 -1
  202. package/dist/record/shadow-pass.d.ts.map +1 -1
  203. package/dist/record/typed-frame-graph.d.ts +49 -2
  204. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  205. package/dist/record/view-ubo.d.ts +1 -2
  206. package/dist/record/view-ubo.d.ts.map +1 -1
  207. package/dist/recovery/render-system-candidate.d.ts +65 -0
  208. package/dist/recovery/render-system-candidate.d.ts.map +1 -0
  209. package/dist/reflection/inspection.d.ts +10 -0
  210. package/dist/reflection/inspection.d.ts.map +1 -0
  211. package/dist/reflection/projection.d.ts +49 -0
  212. package/dist/reflection/projection.d.ts.map +1 -1
  213. package/dist/reflection/record-owner.d.ts +60 -0
  214. package/dist/reflection/record-owner.d.ts.map +1 -0
  215. package/dist/render-contract.d.ts +78 -15
  216. package/dist/render-contract.d.ts.map +1 -1
  217. package/dist/render-pipeline.d.ts +7 -0
  218. package/dist/render-pipeline.d.ts.map +1 -1
  219. package/dist/render-system-extract-tail.d.ts +12 -0
  220. package/dist/render-system-extract-tail.d.ts.map +1 -0
  221. package/dist/render-system-extract.d.ts +252 -30
  222. package/dist/render-system-extract.d.ts.map +1 -1
  223. package/dist/render-system.d.ts +140 -5
  224. package/dist/render-system.d.ts.map +1 -1
  225. package/dist/scene/probe-blend-record.d.ts +22 -0
  226. package/dist/scene/probe-blend-record.d.ts.map +1 -0
  227. package/dist/scene/probe-blend.d.ts +142 -0
  228. package/dist/scene/probe-blend.d.ts.map +1 -0
  229. package/dist/scene/render-scene-types.d.ts +0 -6
  230. package/dist/scene/render-scene-types.d.ts.map +1 -1
  231. package/dist/scene/render-scene.d.ts +122 -9
  232. package/dist/scene/render-scene.d.ts.map +1 -1
  233. package/dist/scene/visibility/bounds.d.ts +20 -0
  234. package/dist/scene/visibility/bounds.d.ts.map +1 -0
  235. package/dist/scene/visibility/budget.d.ts +16 -0
  236. package/dist/scene/visibility/budget.d.ts.map +1 -0
  237. package/dist/scene/visibility/facet.d.ts +73 -0
  238. package/dist/scene/visibility/facet.d.ts.map +1 -0
  239. package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
  240. package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
  241. package/dist/scene/visibility/gpu-lod.d.ts +46 -0
  242. package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
  243. package/dist/scene/visibility/inspection.d.ts +132 -0
  244. package/dist/scene/visibility/inspection.d.ts.map +1 -0
  245. package/dist/scene/visibility/lod-selector.d.ts +25 -0
  246. package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
  247. package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
  248. package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
  249. package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
  250. package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
  251. package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
  252. package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
  253. package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
  254. package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
  255. package/dist/scene/visibility/types.d.ts +34 -0
  256. package/dist/scene/visibility/types.d.ts.map +1 -0
  257. package/dist/ssr/admission.d.ts +122 -0
  258. package/dist/ssr/admission.d.ts.map +1 -0
  259. package/dist/ssr/composition.d.ts +32 -0
  260. package/dist/ssr/composition.d.ts.map +1 -0
  261. package/dist/ssr/errors.d.ts +39 -0
  262. package/dist/ssr/errors.d.ts.map +1 -0
  263. package/dist/ssr/identity.d.ts +13 -0
  264. package/dist/ssr/identity.d.ts.map +1 -0
  265. package/dist/systems/skin-palette-allocator.d.ts +1 -1
  266. package/dist/temporal/frame-coordinator.d.ts +13 -0
  267. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  268. package/dist/temporal/frame.d.ts +2 -0
  269. package/dist/temporal/frame.d.ts.map +1 -1
  270. package/dist/temporal/index.mjs +6 -5
  271. package/dist/temporal/taa-history-store.d.ts +15 -1
  272. package/dist/temporal/taa-history-store.d.ts.map +1 -1
  273. package/dist/temporal/transaction.d.ts +5 -0
  274. package/dist/temporal/transaction.d.ts.map +1 -1
  275. package/dist/temporal/view.d.ts +7 -0
  276. package/dist/temporal/view.d.ts.map +1 -1
  277. package/dist/tilemap-chunk-extract-system.d.ts +1 -1
  278. package/dist/typed-render-graph-primitives.d.ts +4 -0
  279. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  280. package/dist/volume/passes.d.ts +8 -4
  281. package/dist/volume/passes.d.ts.map +1 -1
  282. package/package.json +20 -20
  283. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +5 -0
  284. package/src/__tests__/detached-inspection.integration.test.ts +6 -0
  285. package/src/__tests__/device-feature-admission.unit.test.ts +19 -1
  286. package/src/__tests__/device-loss-fanout.unit.test.ts +107 -0
  287. package/src/__tests__/device-scope-lifecycle.unit.test.ts +21 -0
  288. package/src/__tests__/direct-light-snapshot.unit.test.ts +59 -3
  289. package/src/__tests__/environment-generation.integration.test.ts +39 -0
  290. package/src/__tests__/evidence-identity.ts +13 -0
  291. package/src/__tests__/evidence-identity.unit.test.ts +24 -0
  292. package/src/__tests__/expose-renderer-errors.unit.test.ts +34 -0
  293. package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
  294. package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
  295. package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
  296. package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
  297. package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
  298. package/src/__tests__/factory-contract.integration.test.ts +154 -6
  299. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +4 -1
  300. package/src/__tests__/frame-observation.contract.test.ts +15 -0
  301. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
  302. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +1 -0
  303. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +1 -0
  304. package/src/__tests__/gpu-driven-production.integration.test.ts +572 -9
  305. package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
  306. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
  307. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +89 -2
  308. package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
  309. package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
  310. package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
  311. package/src/__tests__/gpu-lod-evidence.ts +188 -0
  312. package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
  313. package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
  314. package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
  315. package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
  316. package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
  317. package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
  318. package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
  319. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
  320. package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
  321. package/src/__tests__/gpu-scene.unit.test.ts +49 -3
  322. package/src/__tests__/ibl/face-uniforms.unit.test.ts +2 -0
  323. package/src/__tests__/ibl-residency-publication.unit.test.ts +113 -0
  324. package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
  325. package/src/__tests__/light-inspection.unit.test.ts +55 -0
  326. package/src/__tests__/light-resource-error.unit.test.ts +43 -0
  327. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
  328. package/src/__tests__/lod-bounds.unit.test.ts +42 -0
  329. package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
  330. package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
  331. package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
  332. package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
  333. package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
  334. package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
  335. package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
  336. package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
  337. package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
  338. package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
  339. package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
  340. package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
  341. package/src/__tests__/lod-selector.profile.test.ts +35 -0
  342. package/src/__tests__/lod-selector.unit.test.ts +68 -0
  343. package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
  344. package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
  345. package/src/__tests__/ltc-resources.unit.test.ts +32 -0
  346. package/src/__tests__/material-contract-inventory.unit.test.ts +41 -9
  347. package/src/__tests__/material-cooked-projection.unit.test.ts +19 -1
  348. package/src/__tests__/material-static-dynamic-route.unit.test.ts +29 -0
  349. package/src/__tests__/material-stride-surface.unit.test.ts +7 -3
  350. package/src/__tests__/materials-standard-contract.unit.test.ts +104 -0
  351. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
  352. package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
  353. package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
  354. package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
  355. package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
  356. package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
  357. package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
  358. package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
  359. package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
  360. package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
  361. package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
  362. package/src/__tests__/occlusion-query.evidence.ts +178 -0
  363. package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
  364. package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
  365. package/src/__tests__/physical-clearcoat.integration.test.ts +89 -0
  366. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
  367. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +1 -1
  368. package/src/__tests__/probe-bindings.unit.test.ts +200 -0
  369. package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
  370. package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
  371. package/src/__tests__/probe-capacity.integration.test.ts +97 -0
  372. package/src/__tests__/probe-recovery.integration.test.ts +104 -0
  373. package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
  374. package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
  375. package/src/__tests__/profiler-phase-token.test.ts +1 -0
  376. package/src/__tests__/recover-error-policy-owner.unit.test.ts +6 -3
  377. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +140 -0
  378. package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
  379. package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
  380. package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
  381. package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
  382. package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
  383. package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
  384. package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
  385. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
  386. package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
  387. package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
  388. package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
  389. package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
  390. package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
  391. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +160 -17
  392. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +47 -0
  393. package/src/__tests__/renderer-generation-assembly.unit.test.ts +77 -0
  394. package/src/__tests__/renderer-generation-failure.unit.test.ts +108 -0
  395. package/src/__tests__/renderer-producer-root-matrix.integration.test.ts +33 -0
  396. package/src/__tests__/renderer-recovery-capability-matrix.unit.test.ts +59 -0
  397. package/src/__tests__/renderer-recovery-contract.unit.test.ts +73 -0
  398. package/src/__tests__/renderer-recovery-lifecycle.unit.test.ts +216 -0
  399. package/src/__tests__/renderer-target-history-recovery.integration.test.ts +80 -0
  400. package/src/__tests__/shader-manifest-fixture.ts +13 -16
  401. package/src/__tests__/shader-stage-surface.unit.test.ts +1 -1
  402. package/src/__tests__/skin-motion-regression.unit.test.ts +22 -0
  403. package/src/__tests__/skinned-shadow-caster.test.ts +2 -2
  404. package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
  405. package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
  406. package/src/__tests__/ssr-composition.unit.test.ts +46 -0
  407. package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
  408. package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
  409. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +67 -0
  410. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +7 -0
  411. package/src/__tests__/standard-layer-projection.unit.test.ts +23 -0
  412. package/src/__tests__/standard-lighting-inspection.integration.test.ts +1 -1
  413. package/src/__tests__/standard-lighting-write.unit.test.ts +66 -2
  414. package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
  415. package/src/__tests__/temporal-view.unit.test.ts +3 -3
  416. package/src/__tests__/transmission-prewarm.unit.test.ts +111 -32
  417. package/src/__tests__/visibility-budget.integration.test.ts +140 -0
  418. package/src/__tests__/visibility-budget.unit.test.ts +70 -0
  419. package/src/__tests__/visibility-extract.integration.test.ts +11 -6
  420. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
  421. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
  422. package/src/__tests__/volumetric-fog-topology.unit.test.ts +3 -1
  423. package/src/assembly/backend-contract.ts +13 -0
  424. package/src/assembly/bundler-contract.ts +9 -0
  425. package/src/assembly/device-feature-admission.ts +26 -9
  426. package/src/assembly/extended-lighting-fallback.ts +216 -0
  427. package/src/assembly/factory.ts +81 -9634
  428. package/src/assembly/host-contract.ts +10 -0
  429. package/src/assembly/material/assembly.ts +18 -2
  430. package/src/assembly/material/standard-layer-projection.ts +16 -0
  431. package/src/assembly/material-shader-policy.ts +854 -0
  432. package/src/assembly/material-shader-prewarm.ts +88 -0
  433. package/src/assembly/mesh-ssbo-grow.ts +270 -0
  434. package/src/assembly/recovery/device-loss-fanout.ts +89 -0
  435. package/src/assembly/recovery/generation.ts +141 -0
  436. package/src/assembly/recovery/recovery-attempt.ts +800 -0
  437. package/src/assembly/recovery/renderer-recover.ts +906 -0
  438. package/src/assembly/renderer-facade.ts +342 -0
  439. package/src/assembly/renderer-frame-transaction.ts +45 -0
  440. package/src/assembly/renderer-helpers.ts +99 -0
  441. package/src/assembly/renderer-lifecycle.ts +159 -0
  442. package/src/assembly/shader-prewarm-policy.ts +157 -0
  443. package/src/assembly/webgpu-ready-contract.ts +14 -0
  444. package/src/assembly/webgpu-ready.ts +4079 -0
  445. package/src/assembly/webgpu-renderer.ts +4095 -0
  446. package/src/cluster-binner.ts +31 -0
  447. package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
  448. package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
  449. package/src/components/camera.ts +1 -1
  450. package/src/components/index.ts +3 -0
  451. package/src/components/light-helpers.ts +52 -1
  452. package/src/components/light-probe.ts +13 -0
  453. package/src/components/rect-area-light.ts +15 -0
  454. package/src/components/scene-instance.ts +6 -0
  455. package/src/components/spot-light.ts +3 -0
  456. package/src/debug-draw-glue.ts +1 -1
  457. package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
  458. package/src/device/device-scope.ts +35 -6
  459. package/src/device/gpu-residency.ts +334 -35
  460. package/src/device/lifecycle-transaction.ts +12 -0
  461. package/src/environment/frame.ts +6 -0
  462. package/src/environment/inspection.ts +10 -0
  463. package/src/environment/lifecycle.ts +122 -9
  464. package/src/errors/gpu-driven.ts +92 -0
  465. package/src/errors/index.ts +1 -0
  466. package/src/errors/recover.ts +108 -5
  467. package/src/errors/render.ts +72 -1
  468. package/src/extract/camera.ts +3 -3
  469. package/src/extract/contracts.ts +974 -0
  470. package/src/extract/gpu-driven.ts +108 -0
  471. package/src/extract/visibility.ts +0 -23
  472. package/src/features/host.ts +16 -0
  473. package/src/features/prepared-gpu-work.ts +20 -2
  474. package/src/features/prepared-graphics-store.ts +17 -0
  475. package/src/gpu-driven/batch-topology.ts +206 -28
  476. package/src/gpu-driven/prepared-draw.ts +208 -0
  477. package/src/gpu-driven/production-raster.ts +1046 -39
  478. package/src/gpu-driven/view-gpu.ts +411 -29
  479. package/src/gpu-scene-schema.ts +13 -0
  480. package/src/gpu-scene.ts +137 -67
  481. package/src/gpu-usage.ts +0 -1
  482. package/src/hdrp-buffers.ts +6 -6
  483. package/src/ibl/IblPipelineCache.ts +134 -50
  484. package/src/ibl/skylight-bind-group.ts +26 -0
  485. package/src/index.ts +83 -1
  486. package/src/inspection-types.ts +220 -1
  487. package/src/internal.ts +38 -0
  488. package/src/light-buffer-layout.ts +157 -324
  489. package/src/materials.ts +278 -47
  490. package/src/mesh-material-bindings.ts +59 -0
  491. package/src/occlusion-proxy.ts +64 -0
  492. package/src/pbr-pipeline.ts +290 -60
  493. package/src/pipeline/standard-forward-lane.ts +47 -0
  494. package/src/pipeline/standard-lighting/graph.ts +2 -1
  495. package/src/pipeline/standard-lighting/light-frame.ts +3 -2
  496. package/src/pipeline/standard-lighting/topology.ts +1 -1
  497. package/src/pipeline/standard-lighting/transport.ts +2 -1
  498. package/src/pipeline/standard-pipeline.ts +2 -0
  499. package/src/pipeline-builder.ts +5 -2
  500. package/src/pipeline-spec.ts +12 -1
  501. package/src/plugin.ts +4 -0
  502. package/src/points-lines/__tests__/cache-recovery.unit.test.ts +22 -0
  503. package/src/points-lines/prepare.ts +9 -0
  504. package/src/points-lines/standard-owner.ts +403 -0
  505. package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
  506. package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
  507. package/src/prepare/extended-lighting/resources.ts +389 -0
  508. package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
  509. package/src/prepare/extended-lighting/state.ts +92 -0
  510. package/src/record/__tests__/frame-targets-recovery.unit.test.ts +60 -0
  511. package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
  512. package/src/record/__tests__/main-pass-geometry.unit.test.ts +26 -1
  513. package/src/record/__tests__/mesh-ssbo.unit.test.ts +38 -0
  514. package/src/record/__tests__/recovery-pipeline.unit.test.ts +124 -0
  515. package/src/record/__tests__/sprite-material-abi.unit.test.ts +28 -13
  516. package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +47 -4
  517. package/src/record/__tests__/temporal-payload.unit.test.ts +29 -28
  518. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +21 -2
  519. package/src/record/frame-lighting.ts +252 -53
  520. package/src/record/frame-snapshot.ts +72 -12
  521. package/src/record/frame-targets.ts +11 -1
  522. package/src/record/frame.ts +416 -95
  523. package/src/record/gpu-timing.ts +108 -44
  524. package/src/record/helpers.ts +1 -59
  525. package/src/record/main-pass-geometry.ts +434 -44
  526. package/src/record/main-pass-material.ts +324 -210
  527. package/src/record/main-pass-sprite-draws.ts +58 -92
  528. package/src/record/main-pass.ts +94 -6
  529. package/src/record/mesh-ssbo.ts +79 -46
  530. package/src/record/recovery-pipeline.ts +695 -0
  531. package/src/record/render-context.ts +99 -7
  532. package/src/record/shadow-pass.ts +66 -40
  533. package/src/record/typed-frame-graph.ts +270 -84
  534. package/src/record/view-ubo.ts +17 -27
  535. package/src/recovery/render-system-candidate.ts +839 -0
  536. package/src/reflection/inspection.ts +67 -0
  537. package/src/reflection/projection.ts +196 -1
  538. package/src/reflection/record-owner.ts +1283 -0
  539. package/src/render-contract.ts +82 -12
  540. package/src/render-pipeline.ts +5 -0
  541. package/src/render-system-extract-tail.ts +2983 -0
  542. package/src/render-system-extract.ts +290 -2784
  543. package/src/render-system.ts +1597 -1192
  544. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
  545. package/src/scene/probe-blend-record.ts +54 -0
  546. package/src/scene/probe-blend.ts +813 -0
  547. package/src/scene/render-scene-types.ts +0 -7
  548. package/src/scene/render-scene.ts +972 -184
  549. package/src/scene/visibility/bounds.ts +57 -0
  550. package/src/scene/visibility/budget.ts +40 -0
  551. package/src/scene/visibility/facet.ts +400 -0
  552. package/src/scene/visibility/gpu-frame-timing.ts +101 -0
  553. package/src/scene/visibility/gpu-lod.ts +119 -0
  554. package/src/scene/visibility/inspection.ts +313 -0
  555. package/src/scene/visibility/lod-selector.ts +84 -0
  556. package/src/scene/visibility/occlusion-confidence.ts +478 -0
  557. package/src/scene/visibility/occlusion-pass.ts +165 -0
  558. package/src/scene/visibility/occlusion-query-pool.ts +178 -0
  559. package/src/scene/visibility/occlusion-runtime.ts +672 -0
  560. package/src/scene/visibility/types.ts +50 -0
  561. package/src/ssr/admission.ts +451 -0
  562. package/src/ssr/composition.ts +73 -0
  563. package/src/ssr/errors.ts +76 -0
  564. package/src/ssr/identity.ts +12 -0
  565. package/src/systems/skin-palette-allocator.ts +1 -1
  566. package/src/temporal/frame-coordinator.ts +30 -1
  567. package/src/temporal/frame.ts +14 -1
  568. package/src/temporal/taa-history-store.ts +46 -2
  569. package/src/temporal/temporal-view.ts +1 -1
  570. package/src/temporal/transaction.ts +9 -0
  571. package/src/temporal/view.ts +11 -0
  572. package/src/tilemap-chunk-extract-system.ts +5 -5
  573. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +19 -12
  574. package/src/typed-render-graph-primitives.ts +48 -0
  575. package/src/volume/passes.ts +46 -49
  576. package/dist/.tsbuildinfo +0 -1
  577. package/dist/chunk-5YADUCA7.mjs.map +0 -1
  578. package/dist/chunk-6OPXDQ2E.mjs.map +0 -1
  579. package/dist/chunk-BXBQQKFQ.mjs +0 -67
  580. package/dist/chunk-BXBQQKFQ.mjs.map +0 -1
  581. package/dist/chunk-FS2KNUQH.mjs.map +0 -1
  582. package/dist/chunk-PCHBPYML.mjs.map +0 -1
  583. package/dist/chunk-VFPLTKCU.mjs +0 -192
  584. package/dist/chunk-VFPLTKCU.mjs.map +0 -1
@@ -25,14 +25,18 @@ import type {
25
25
  BindGroup,
26
26
  BindGroupEntry,
27
27
  BindGroupLayout,
28
- BindGroupLayoutDescriptor,
29
28
  Buffer,
30
29
  PipelineLayout,
31
30
  RhiDevice,
32
31
  Sampler,
32
+ TextureFormat,
33
33
  TextureView,
34
34
  } from '@forgeax/engine-rhi';
35
- import { DEFAULT_STANDARD_PBR_PARAM_SCHEMA, type ShaderCatalog } from '@forgeax/engine-shader';
35
+ import {
36
+ type ShaderCatalog,
37
+ STANDARD_PIPELINE_PARAM_SCHEMA,
38
+ standardPhysicalTextureFields,
39
+ } from '@forgeax/engine-shader';
36
40
  import { derive, type ParamSchemaEntry } from '@forgeax/engine-types';
37
41
  import { GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX } from './gpu-stage';
38
42
  import type { PipelineSpec } from './pipeline-spec-types';
@@ -72,6 +76,10 @@ export interface PbrPipelineLayoutBundle {
72
76
  readonly meshArrayBgl: BindGroupLayout;
73
77
  /** Per-instance storage BindGroupLayout (slot 3). */
74
78
  readonly instancesBgl: BindGroupLayout;
79
+ /** Probe-enabled slot-3 BGL; aliases `instancesBgl` when probes are unavailable. */
80
+ readonly probeInstancesBgl: BindGroupLayout;
81
+ /** Same pipeline layout with the probe-enabled slot-3 BGL, when supported. */
82
+ readonly probePipelineLayout: PipelineLayout | null;
75
83
  /**
76
84
  * Same 4 layouts in slot order. Useful for assertion sites that check the
77
85
  * pipeline-layout `bindGroupLayouts` array shape (t57 (a) + (d)).
@@ -84,16 +92,26 @@ export interface PbrPipelineLayoutBundle {
84
92
  ];
85
93
  }
86
94
 
95
+ /** Derives the Standard PBR attachment list without allocating a closed path. */
96
+ export function standardPbrColorFormats(
97
+ baseFormat: TextureFormat,
98
+ fallbackDemand: boolean,
99
+ ): readonly TextureFormat[] {
100
+ return fallbackDemand ? [baseFormat, 'rgba16float'] : [baseFormat];
101
+ }
102
+
87
103
  // ─── Base entries (round-4 SSOT) ────────────────────────────────────────────
88
104
 
89
105
  /**
90
106
  * The built-in standard-PBR material paramSchema's texture/user-region shape,
91
107
  * used as the fallback when the material BGL is built without a registry
92
- * (the caps-driven `buildPbrPipelineLayouts` seam). Declares the 8 Standard
93
- * user-region textures + a numeric UBO run; `derive()` collapses the numerics
94
- * into binding 0 and emits sampler/texture pairs at 1..6 — byte-equivalent to
95
- * the legacy fixed base-7. The shared PBR parameter contract comes from the
96
- * shader package; this module only derives the GPU layout.
108
+ * (the caps-driven `buildPbrPipelineLayouts` seam). Declares the canonical
109
+ * Standard user-region textures + a numeric UBO run; `derive()` collapses the
110
+ * numerics into binding 0 and emits one sampler/texture pair per declared
111
+ * texture. Physical map pairs stay outside this boot region and are appended
112
+ * only for an authored root that declares them. The shared PBR parameter
113
+ * contract comes from the shader package; this module only derives the GPU
114
+ * layout.
97
115
  */
98
116
  /**
99
117
  * Build the PBR material BGL **user-region** from a paramSchema via the
@@ -104,9 +122,10 @@ export interface PbrPipelineLayoutBundle {
104
122
  * custom schema (e.g. parallax + heightTexture) shifts the injection region by
105
123
  * one sampler/texture pair automatically.
106
124
  *
107
- * The built-in `default-standard-pbr` paramSchema declares exactly 8 textures,
108
- * so this derives to binding 0 UBO + 8 pairs = 17 entries. Injection is appended
109
- * after that derived region.
125
+ * The canonical `STANDARD_PIPELINE_PARAM_SCHEMA` currently declares seven
126
+ * non-physical textures, so this derives to binding 0 UBO + seven pairs = 15
127
+ * entries. IBL and transmission injection are appended after that region;
128
+ * authored physical maps are appended after the engine-owned injections.
110
129
  *
111
130
  * One material-UBO convention is layered on top of the pure `derive()` output:
112
131
  * binding 0 is patched to `{ type: 'uniform', hasDynamicOffset: true }` with
@@ -120,9 +139,18 @@ export interface PbrPipelineLayoutBundle {
120
139
  * built-in standard-PBR shape when omitted, for the caps-driven seam).
121
140
  */
122
141
  export function buildPbrMaterialUserRegionEntries(
123
- paramSchema: readonly ParamSchemaEntry[] = DEFAULT_STANDARD_PBR_PARAM_SCHEMA,
142
+ paramSchema: readonly ParamSchemaEntry[] = STANDARD_PIPELINE_PARAM_SCHEMA,
143
+ excludedTextureFields: readonly string[] = [],
124
144
  ): GPUBindGroupLayoutEntry[] {
125
- const derived = derive(paramSchema);
145
+ const excluded = new Set(excludedTextureFields);
146
+ for (const field of standardPhysicalTextureFields(paramSchema)) excluded.add(field);
147
+ const derived = derive(
148
+ excluded.size === 0
149
+ ? paramSchema
150
+ : paramSchema.filter(
151
+ (entry) => !excluded.has(entry.name) || !entry.type.startsWith('texture'),
152
+ ),
153
+ );
126
154
  // Project the engine-owned entry shape into the DOM WebGPU descriptor. Omit
127
155
  // absent optional members so exactOptionalPropertyTypes remains true at the
128
156
  // boundary instead of leaking an `undefined` property into the descriptor.
@@ -318,6 +346,68 @@ export const INJECTION_KIND_LENGTHS = {
318
346
  transmission: TRANSMISSION_INJECTION_LENGTH,
319
347
  };
320
348
 
349
+ export function physicalTextureFields(paramSchema: readonly ParamSchemaEntry[]): readonly string[] {
350
+ return standardPhysicalTextureFields(paramSchema);
351
+ }
352
+
353
+ export function appendTextureInjection(
354
+ bgl: readonly GPUBindGroupLayoutEntry[],
355
+ fields: readonly string[],
356
+ ): GPUBindGroupLayoutEntry[] {
357
+ const start = bgl.length;
358
+ const fieldSet = new Set(fields);
359
+ return standardPhysicalTextureFields(
360
+ fields.map((name) => ({ name, type: 'texture2d' as const })),
361
+ ).flatMap((field, index) => {
362
+ if (!fieldSet.has(field)) return [];
363
+ const binding = start + index * 2;
364
+ return [
365
+ {
366
+ binding,
367
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
368
+ sampler: { type: 'filtering' as const },
369
+ },
370
+ {
371
+ binding: binding + 1,
372
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
373
+ texture: { sampleType: 'float' as const, viewDimension: '2d' as const },
374
+ },
375
+ ];
376
+ });
377
+ }
378
+
379
+ /**
380
+ * Return the stable identity of the merged material bind-group layout.
381
+ *
382
+ * This is deliberately derived from the same descriptor builder consumed by
383
+ * the device path. Callers use it to keep pipeline, bind-group, and
384
+ * frame-local lookup caches on one layout identity even when equivalent
385
+ * paramSchema arrays were allocated independently.
386
+ */
387
+ export function materialBindGroupLayoutIdentity(
388
+ shaderId: string,
389
+ paramSchema: readonly ParamSchemaEntry[],
390
+ ): string {
391
+ const descriptor = buildBindGroupLayoutDescriptor(
392
+ {
393
+ shader: { id: shaderId, passKind: 'forward', variantSet: undefined },
394
+ attachments: { colorFormats: [], depthFormat: undefined, sampleCount: 1 },
395
+ geometry: { topology: 'triangle-list', vertexLayout: {} },
396
+ renderState: undefined,
397
+ },
398
+ { kind: 'pbr-material-merged', materialParamSchema: paramSchema },
399
+ );
400
+ // Descriptor shape alone cannot distinguish two Standard roots that expose
401
+ // the same number of physical texture pairs under different semantic names.
402
+ // The resource order is part of the admitted root contract, so include the
403
+ // canonical physical projection in the cache identity while keeping the
404
+ // actual WebGPU descriptor owned by the builder above.
405
+ return JSON.stringify({
406
+ entries: descriptor.entries,
407
+ physicalTextureFields: physicalTextureFields(paramSchema),
408
+ });
409
+ }
410
+
321
411
  /**
322
412
  * Caps shape consumed by the BGL factory functions for storage-buffer vs
323
413
  * uniform-buffer branching. Mirrors the two fields the engine reads from
@@ -325,14 +415,21 @@ export const INJECTION_KIND_LENGTHS = {
325
415
  */
326
416
  export interface PbrCaps {
327
417
  readonly storageBuffer: boolean;
418
+ /**
419
+ * Whether the selected material variant declares the optional extended
420
+ * lighting view resources. The default keeps the historical helper shape
421
+ * for callers that build the canonical full PBR layout; the renderer passes
422
+ * the device/variant decision explicitly.
423
+ */
424
+ readonly extendedLighting?: boolean;
425
+ /** Selects the optional binding(1) ProbeBlendRecord lane. */
426
+ readonly probeBlend?: boolean;
328
427
  /** Whether the device can carry the optional SpotLight projector texture. */
329
428
  readonly projectorAvailable?: boolean;
330
429
  }
331
430
 
332
431
  /**
333
432
  * The view BGL entry list. binding 0 = view UBO (vertex + fragment);
334
- * binding 1 = pointLights (storage or uniform, per caps);
335
- * binding 2 = spotLights (storage or uniform, per caps);
336
433
  * binding 3 = directional shadowMap atlas (texture_depth_2d, vertex+fragment).
337
434
  * feat-20260613-csm-cascaded-shadow-maps: this is the CSM atlas — N
338
435
  * cascades tiled into one 2D depth texture, sampled via per-cascade UV
@@ -372,12 +469,11 @@ export interface PbrCaps {
372
469
  * layout and consumed only by the dedicated points-lines shader).
373
470
  * Isolated here so M4 round-4 tests can recreate the layout.
374
471
  *
375
- * feat-20260526-pbr-uniform-fallback-no-storage-buffer M3 / w9:
376
- * caps.storageBuffer===false switches bindings 1+2 from
377
- * 'read-only-storage' to 'uniform'.
472
+ * Local lights are not part of the view group. Standard material variants
473
+ * consume the one Cluster payload in group(2), while this group retains only
474
+ * camera and shadow resources.
378
475
  */
379
476
  export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[] {
380
- const lightBufType: GPUBufferBindingType = caps.storageBuffer ? 'read-only-storage' : 'uniform';
381
477
  const entries: GPUBindGroupLayoutEntry[] = [
382
478
  {
383
479
  binding: 0,
@@ -386,16 +482,6 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
386
482
  // Keeping this dynamic is also valid for the display slot at offset 0.
387
483
  buffer: { type: 'uniform', hasDynamicOffset: true },
388
484
  },
389
- {
390
- binding: 1,
391
- visibility: GPU_SHADER_STAGE_FRAGMENT,
392
- buffer: { type: lightBufType },
393
- },
394
- {
395
- binding: 2,
396
- visibility: GPU_SHADER_STAGE_FRAGMENT,
397
- buffer: { type: lightBufType },
398
- },
399
485
  {
400
486
  binding: 3,
401
487
  visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
@@ -422,9 +508,9 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
422
508
  // shadow-casting point light slot (shadowAtlasLayer in [0, 4)). Each
423
509
  // lane stores `(near, far, 1/(far-near), 0)` so the fragment-shader
424
510
  // depth-ref reconstruction (lighting-punctual.wgsl evalPointShadowed)
425
- // can avoid sampling LightSlot for the URP path. HDRP rides the same
426
- // constants on `LightSlot.kind_and_pad.zw` so binding 6 is unused on
427
- // HDRP shaders even though the BGL declares it (charter P4 single SSOT
511
+ // can avoid sampling DirectLightSlot for the URP path. The shared
512
+ // DirectLightSlot metadata remains the identity owner, so binding 6 is
513
+ // unused on HDRP shaders even though the BGL declares it (charter P4 single SSOT
428
514
  // BGL across pipelines; the HDRP variant simply doesn't reference the
429
515
  // binding in WGSL, which is allowed).
430
516
  {
@@ -474,12 +560,41 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
474
560
  texture: { sampleType: 'depth', viewDimension: '2d' },
475
561
  },
476
562
  ];
477
- // The projector is optional, but when present it is a sampled texture in
478
- // the fragment stage. Keep it out of the low-limit view layout so the
479
- // remaining HDRP PBR ABI stays within WebGPU's minimum 16 sampled textures.
480
- // The corresponding PROJECTOR_AVAILABLE shader variant is selected from
481
- // the same device capability bit and returns a white modulation.
482
- if (caps.projectorAvailable !== false) {
563
+ const extendedLighting = caps.extendedLighting ?? true;
564
+ if (extendedLighting) {
565
+ entries.push(
566
+ {
567
+ binding: 9,
568
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
569
+ sampler: { type: 'filtering' },
570
+ },
571
+ {
572
+ binding: 11,
573
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
574
+ texture: { sampleType: 'float', viewDimension: '2d-array' },
575
+ },
576
+ {
577
+ binding: 12,
578
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
579
+ texture: { sampleType: 'float', viewDimension: '2d-array' },
580
+ },
581
+ {
582
+ binding: 13,
583
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
584
+ texture: { sampleType: 'float', viewDimension: '2d' },
585
+ },
586
+ {
587
+ binding: 14,
588
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
589
+ texture: { sampleType: 'float', viewDimension: '2d' },
590
+ },
591
+ {
592
+ binding: 15,
593
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
594
+ buffer: { type: 'uniform' },
595
+ },
596
+ );
597
+ } else if (caps.projectorAvailable !== false) {
483
598
  entries.push(
484
599
  {
485
600
  binding: 11,
@@ -508,8 +623,8 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
508
623
  * material, mesh-array, instances]`; the material BGL is derived from the
509
624
  * standard material schema and engine injection chain.
510
625
  *
511
- * `caps.storageBuffer===false` switches every storage-buffer BGL entry
512
- * (view bindings 1+2, mesh-array, instances) to `uniform`.
626
+ * `caps.storageBuffer===false` switches the mesh-array and instances entries
627
+ * to `uniform`; local-light resources are never part of this view group.
513
628
  *
514
629
  * Throws on each `createBindGroupLayout` / `createPipelineLayout` Result
515
630
  * failure -- the engine bootstrap path (createRenderer) wraps the call in
@@ -531,7 +646,7 @@ export function buildPbrPipelineLayouts(
531
646
 
532
647
  // Material BGL: derived user region + Skylight + transmission injection.
533
648
  // The transmission start binding is computed from the post-Skylight BGL
534
- // length (= 24 for the built-in Standard schema) by appendInjection.
649
+ // length (= 22 for the canonical Standard schema) by appendInjection.
535
650
  const materialBglRes = device.createBindGroupLayout(
536
651
  buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'pbr-material-merged' }),
537
652
  );
@@ -545,9 +660,27 @@ export function buildPbrPipelineLayouts(
545
660
 
546
661
  // instances BGL.
547
662
  const instancesBglRes = device.createBindGroupLayout(
548
- buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'pbr-instances', caps }),
663
+ buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
664
+ kind: 'pbr-instances',
665
+ caps: { ...caps, probeBlend: false },
666
+ }),
549
667
  );
550
668
  if (!instancesBglRes.ok) throw instancesBglRes.error;
669
+ // ProbeBlendRecord is a storage-buffer-only ABI extension. A uniform
670
+ // fallback cannot afford the extra fragment-stage uniform binding on
671
+ // WebGL2/GLES, so do not even construct the probe BGL on that capability
672
+ // route. The record stage gates the matching variant and bind group with
673
+ // the same storage capability; aliasing the ordinary BGL keeps the bundle
674
+ // total and makes an accidental probe request fail closed at layout select.
675
+ const probeInstancesBglRes = caps.storageBuffer
676
+ ? device.createBindGroupLayout(
677
+ buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
678
+ kind: 'pbr-instances',
679
+ caps: { ...caps, probeBlend: true },
680
+ }),
681
+ )
682
+ : { ok: true as const, value: instancesBglRes.value };
683
+ if (!probeInstancesBglRes.ok) throw probeInstancesBglRes.error;
551
684
 
552
685
  // Pipeline layout (4 slots).
553
686
  const layouts: readonly [BindGroupLayout, BindGroupLayout, BindGroupLayout, BindGroupLayout] = [
@@ -561,6 +694,21 @@ export function buildPbrPipelineLayouts(
561
694
  bindGroupLayouts: layouts,
562
695
  });
563
696
  if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
697
+ const probeLayouts: readonly [
698
+ BindGroupLayout,
699
+ BindGroupLayout,
700
+ BindGroupLayout,
701
+ BindGroupLayout,
702
+ ] = [viewBglRes.value, materialBglRes.value, meshArrayBglRes.value, probeInstancesBglRes.value];
703
+ let probePipelineLayout: PipelineLayout | null = null;
704
+ if (caps.storageBuffer) {
705
+ const probePipelineLayoutRes = device.createPipelineLayout({
706
+ label: 'pbr-probe-pl',
707
+ bindGroupLayouts: probeLayouts,
708
+ });
709
+ if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;
710
+ probePipelineLayout = probePipelineLayoutRes.value;
711
+ }
564
712
 
565
713
  return {
566
714
  pipelineLayout: pipelineLayoutRes.value,
@@ -568,6 +716,8 @@ export function buildPbrPipelineLayouts(
568
716
  materialBgl: materialBglRes.value,
569
717
  meshArrayBgl: meshArrayBglRes.value,
570
718
  instancesBgl: instancesBglRes.value,
719
+ probeInstancesBgl: probeInstancesBglRes.value,
720
+ probePipelineLayout,
571
721
  bindGroupLayouts: layouts,
572
722
  };
573
723
  }
@@ -586,6 +736,21 @@ export function buildPbrPipelineLayouts(
586
736
  export const SKIN_MATERIAL_SHADER_ID = 'forgeax::pbr-skin' as const;
587
737
  export const SHADOW_CASTER_SHADER_ID = 'forgeax::default-shadow-caster' as const;
588
738
 
739
+ // Authored Standard templates are published under a unique module id for each
740
+ // root contract. Keep the family marker in the id so every downstream render
741
+ // owner (extract, layout, and record) can make the same Standard-vs-custom and
742
+ // rigid-vs-skinned decision without a second registry or a runtime shader
743
+ // inspection pass.
744
+ const AUTHORED_STANDARD_ID_RE = /::(?:standard|pbr-skin)(?:-|$)/;
745
+
746
+ export function isStandardPbrSkinMaterialShader(shaderId: string | undefined): boolean {
747
+ return (
748
+ shaderId === SKIN_MATERIAL_SHADER_ID ||
749
+ shaderId === 'forgeax::default-standard-pbr-skin' ||
750
+ (shaderId !== undefined && /::pbr-skin(?:-|$)/.test(shaderId))
751
+ );
752
+ }
753
+
589
754
  export function shadowCasterVariantSet(storageBuffer: boolean, skinned: boolean): string {
590
755
  const skinningDisabled = !skinned;
591
756
  if (storageBuffer && skinningDisabled) return '';
@@ -620,6 +785,22 @@ export function resolvePipelineGroup2Contract(source: string): PipelineGroup2Con
620
785
 
621
786
  /** Returns true for the engine-shipped standard-PBR material shader family. */
622
787
  export function isStandardPbrMaterialShader(shaderId: string | undefined): boolean {
788
+ return (
789
+ shaderId === 'forgeax::default-standard-pbr' ||
790
+ shaderId === SKIN_MATERIAL_SHADER_ID ||
791
+ shaderId === 'forgeax::default-standard-pbr-skin' ||
792
+ (shaderId !== undefined && AUTHORED_STANDARD_ID_RE.test(shaderId))
793
+ );
794
+ }
795
+
796
+ /**
797
+ * Return true only for the two engine-owned Standard roots. Authored Standard
798
+ * aliases intentionally remain outside this set: their cooked root schema may
799
+ * omit transmission or other optional resources, so their compact user-region
800
+ * layout must be derived from that artifact instead of borrowing the boot
801
+ * layout's reserved slots.
802
+ */
803
+ export function isCanonicalStandardPbrMaterialShader(shaderId: string | undefined): boolean {
623
804
  return (
624
805
  shaderId === 'forgeax::default-standard-pbr' ||
625
806
  shaderId === SKIN_MATERIAL_SHADER_ID ||
@@ -685,6 +866,21 @@ export function buildPbrSkinLayouts(
685
866
  bindGroupLayouts: layouts,
686
867
  });
687
868
  if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
869
+ const probeLayouts: readonly [
870
+ BindGroupLayout,
871
+ BindGroupLayout,
872
+ BindGroupLayout,
873
+ BindGroupLayout,
874
+ ] = [pbr.viewBgl, pbr.materialBgl, skinMeshArrayBglRes.value, pbr.probeInstancesBgl];
875
+ let probePipelineLayout: PipelineLayout | null = null;
876
+ if (caps.storageBuffer) {
877
+ const probePipelineLayoutRes = device.createPipelineLayout({
878
+ label: 'pbr-skin-probe-pl',
879
+ bindGroupLayouts: probeLayouts,
880
+ });
881
+ if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;
882
+ probePipelineLayout = probePipelineLayoutRes.value;
883
+ }
688
884
 
689
885
  return {
690
886
  pipelineLayout: pipelineLayoutRes.value,
@@ -692,6 +888,8 @@ export function buildPbrSkinLayouts(
692
888
  materialBgl: pbr.materialBgl,
693
889
  meshArrayBgl: skinMeshArrayBglRes.value,
694
890
  instancesBgl: pbr.instancesBgl,
891
+ probeInstancesBgl: pbr.probeInstancesBgl,
892
+ probePipelineLayout,
695
893
  bindGroupLayouts: layouts,
696
894
  };
697
895
  }
@@ -860,8 +1058,9 @@ export const SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET = '';
860
1058
  * - `'unlit-material'` — 7 entries: base PBR material only (no inject)
861
1059
  * - `'hdrp-7-slot'` — 7 entries (binding 0 + 3..8): HDRP cluster + SSAO group(2) BGL
862
1060
  * 2. Caps-driven literal shapes (no shader):
863
- * - `'pbr-view'` — 12 entries: view UBO + lights + shadow bindings,
864
- * projector texture/sampler (11/12), and the Points/Lines UBO (10)
1061
+ * - `'pbr-view'` — camera/shadow bindings, optional projector
1062
+ * texture/sampler (11/12), and the Points/Lines UBO (10). Local lights
1063
+ * are carried exclusively by the Standard Cluster group(2).
865
1064
  * (directional 3/4, point 5/6, cascade 7, spot atlas 8; the former
866
1065
  * spot lightViewProj matrices moved into the View UBO)
867
1066
  * - `'pbr-mesh-array'` — 1 entry: per-entity mesh SSBO (dynamic-offset)
@@ -909,7 +1108,7 @@ export interface BindGroupLayoutDescriptorOutput {
909
1108
  }
910
1109
 
911
1110
  /** Build the canonical HDRP group(2) bind-group layout. */
912
- export function createHdrpBindGroupLayoutDescriptor(): BindGroupLayoutDescriptor {
1111
+ export function createHdrpBindGroupLayoutDescriptor(): BindGroupLayoutDescriptorOutput {
913
1112
  const meshBufType: GPUBufferBindingType = 'read-only-storage';
914
1113
  const clusterBufType: GPUBufferBindingType = 'read-only-storage';
915
1114
  return {
@@ -961,7 +1160,7 @@ export function createHdrpBindGroupLayoutDescriptor(): BindGroupLayoutDescriptor
961
1160
  }
962
1161
 
963
1162
  /** Build the HDRP group(2) layout for the clustered skin variant. */
964
- export function createHdrpSkinBindGroupLayoutDescriptor(): BindGroupLayoutDescriptor {
1163
+ export function createHdrpSkinBindGroupLayoutDescriptor(): BindGroupLayoutDescriptorOutput {
965
1164
  const base = createHdrpBindGroupLayoutDescriptor();
966
1165
  const baseEntries = base.entries;
967
1166
  if (baseEntries === undefined || baseEntries[0] === undefined) {
@@ -1088,19 +1287,35 @@ export function buildBindGroupLayoutDescriptor(
1088
1287
  const meshBufType: GPUBufferBindingType = caps.storageBuffer
1089
1288
  ? 'read-only-storage'
1090
1289
  : 'uniform';
1290
+ const entries: GPUBindGroupLayoutEntry[] = [
1291
+ {
1292
+ binding: 0,
1293
+ visibility: GPU_SHADER_STAGE_VERTEX,
1294
+ buffer: { type: meshBufType, hasDynamicOffset: false },
1295
+ },
1296
+ ...(caps.probeBlend === true
1297
+ ? [
1298
+ {
1299
+ // Per-object fragment lane; the record is always exactly 160B.
1300
+ binding: 1,
1301
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
1302
+ buffer: { type: meshBufType, hasDynamicOffset: true },
1303
+ },
1304
+ ]
1305
+ : []),
1306
+ ];
1091
1307
  return {
1092
- label: 'pbr-instances-bgl',
1093
- entries: [
1094
- {
1095
- binding: 0,
1096
- // Standard transmission reads the same per-instance transform in
1097
- // fs_main to convert glTF unit-space thickness into world metres.
1098
- // Keep one shared instances BGL and widen its visibility instead
1099
- // of introducing a second transform upload or six new varyings.
1100
- visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
1101
- buffer: { type: meshBufType, hasDynamicOffset: false },
1102
- },
1103
- ],
1308
+ label: caps.probeBlend === true ? 'pbr-probe-instances-bgl' : 'pbr-instances-bgl',
1309
+ entries: entries.map((entry) =>
1310
+ entry.binding === 0
1311
+ ? {
1312
+ ...entry,
1313
+ // Standard transmission reads the same per-instance transform in
1314
+ // fs_main to convert glTF unit-space thickness into world metres.
1315
+ visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
1316
+ }
1317
+ : entry,
1318
+ ),
1104
1319
  };
1105
1320
  }
1106
1321
  case 'pbr-skin-mesh-array': {
@@ -1134,14 +1349,29 @@ export function buildBindGroupLayoutDescriptor(
1134
1349
  // + IBL injection (7) + transmission injection (2). The user-region
1135
1350
  // size is the only variable; injection start = userRegion.length so a
1136
1351
  // custom schema shifts IBL/transmission by its sampler/texture pairs.
1137
- // The built-in 8-texture standard-PBR schema is 17 + 7 + 2 = 26 entries.
1352
+ // The built-in standard-PBR schema is 17 + 7 + 2 = 26 entries;
1353
+ // clearcoat texture pairs are derived from the effective root schema.
1138
1354
  //
1139
1355
  // Schema source priority (D-1): explicit materialParamSchema option >
1140
1356
  // registry lookup of spec.shader.id > built-in standard-PBR fallback.
1141
1357
  const resolvedSchema = resolveMaterialParamSchema(spec, options);
1142
- const userRegion = buildPbrMaterialUserRegionEntries(resolvedSchema);
1358
+ const effectiveSchema = resolvedSchema ?? STANDARD_PIPELINE_PARAM_SCHEMA;
1359
+ const physicalFields = physicalTextureFields(effectiveSchema);
1360
+ // Standard's built-in shader keeps the transmission user-region slots
1361
+ // reserved even when a particular root omits those values. Physical
1362
+ // maps extend that canonical region; they must not compact the IBL
1363
+ // bindings to the smaller authored subset. A compact user region is
1364
+ // still correct for authored (non-engine) material shaders.
1365
+ const userRegionSchema = isCanonicalStandardPbrMaterialShader(spec.shader.id)
1366
+ ? STANDARD_PIPELINE_PARAM_SCHEMA
1367
+ : effectiveSchema;
1368
+ const userRegion = buildPbrMaterialUserRegionEntries(userRegionSchema);
1143
1369
  const afterIbl = [...userRegion, ...appendInjection(userRegion, 'ibl')];
1144
- const merged = [...afterIbl, ...appendInjection(afterIbl, 'transmission')];
1370
+ const afterTransmission = [...afterIbl, ...appendInjection(afterIbl, 'transmission')];
1371
+ const merged = [
1372
+ ...afterTransmission,
1373
+ ...appendTextureInjection(afterTransmission, physicalFields),
1374
+ ];
1145
1375
  return {
1146
1376
  label: 'pbr-material-skylight-bgl',
1147
1377
  entries: merged,
@@ -5,6 +5,11 @@ import type {
5
5
  } from '@forgeax/engine-render-graph';
6
6
  import { err, ok, type Result } from '@forgeax/engine-types';
7
7
  import { SceneDataUnavailableError } from '../errors/render';
8
+ import {
9
+ GPU_TEXTURE_USAGE_COPY_SRC,
10
+ GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
11
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING,
12
+ } from '../gpu-texture-usage';
8
13
  import type {
9
14
  RenderPipeline,
10
15
  RenderPipelineBuildContext,
@@ -29,6 +34,7 @@ import {
29
34
  transmissionDemandForTopology,
30
35
  } from '../transmission/backdrop';
31
36
  import {
37
+ addReflectionFallbackObservationPass,
32
38
  addTypedFrameObservationPass,
33
39
  addTypedScenePass,
34
40
  addTypedSkyboxPass,
@@ -135,6 +141,35 @@ function buildUrp(
135
141
  : sceneResolved;
136
142
  if (!scene.ok) return scene;
137
143
 
144
+ const reflectionFallback = topology.reflectionFallback?.enabled
145
+ ? target(graph, 'reflection-fallback-linear-hdr', {
146
+ format: 'rgba16float',
147
+ size: 'surface',
148
+ sampleCount: scene.value.sampleCount,
149
+ domain: 'linear-hdr',
150
+ usage:
151
+ GPU_TEXTURE_USAGE_COPY_SRC |
152
+ GPU_TEXTURE_USAGE_RENDER_ATTACHMENT |
153
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING,
154
+ })
155
+ : ok(undefined);
156
+ if (!reflectionFallback.ok) return reflectionFallback;
157
+ if (reflectionFallback.value !== undefined) {
158
+ const initialized = graph.addRasterPass('reflection-fallback-clear', {
159
+ accesses: [{ resource: reflectionFallback.value.view, usage: 'color-attachment' }],
160
+ colorAttachments: [
161
+ {
162
+ view: reflectionFallback.value.view,
163
+ loadOp: 'clear',
164
+ storeOp: 'store',
165
+ clearValue: { r: 0, g: 0, b: 0, a: 0 },
166
+ },
167
+ ],
168
+ encode: () => {},
169
+ });
170
+ if (!initialized.ok) return initialized;
171
+ }
172
+
138
173
  const shadows = addTypedShadowPasses(graph, topology);
139
174
  if (!shadows.ok) return shadows;
140
175
 
@@ -163,6 +198,9 @@ function buildUrp(
163
198
  const main = addTypedScenePass(graph, {
164
199
  name: 'main',
165
200
  color: scene.value,
201
+ ...(reflectionFallback.value === undefined
202
+ ? {}
203
+ : { colorTargets: [scene.value, reflectionFallback.value] }),
166
204
  depth: depth.value,
167
205
  ...(msaa ? { resolve: sceneResolved.value } : {}),
168
206
  sampled: [
@@ -179,6 +217,7 @@ function buildUrp(
179
217
  extraAccesses: clusterReads,
180
218
  ...(transmissionActive ? { recordMode: 'opaque' as const } : {}),
181
219
  ...(gpuDriven.value === undefined ? {} : { gpuDriven: gpuDriven.value }),
220
+ ...(context.occlusion === undefined ? {} : { occlusion: context.occlusion }),
182
221
  });
183
222
  if (!main.ok) return main;
184
223
 
@@ -286,6 +325,7 @@ function buildUrp(
286
325
  depthSample.value,
287
326
  shadows.value.directional?.view,
288
327
  shadows.value.spot.view,
328
+ clusterBuffers.value,
289
329
  );
290
330
  if (!volume.ok) return volume;
291
331
  }
@@ -318,6 +358,13 @@ function buildUrp(
318
358
  );
319
359
  if (!observation.ok) return observation;
320
360
  }
361
+ if (reflectionFallback.value?.sampleCount === 1) {
362
+ const fallbackObservation = addReflectionFallbackObservationPass(
363
+ graph,
364
+ reflectionFallback.value,
365
+ );
366
+ if (!fallbackObservation.ok) return fallbackObservation;
367
+ }
321
368
 
322
369
  const post = addStandardPost(
323
370
  context,
@@ -11,6 +11,7 @@ import {
11
11
  GPU_BUFFER_USAGE_UNIFORM,
12
12
  } from '../../gpu-usage';
13
13
  import { getOrCreateHdrpBuffers, type HdrpBuffers } from '../../hdrp-buffers';
14
+ import { BYTES_PER_DIRECT_LIGHT_SLOT } from '../../light-buffer-layout';
14
15
  import type { _InternalRenderPipelineContext } from '../../record/render-context';
15
16
  import type { RenderPipelineFrame } from '../../render-pipeline';
16
17
  import type { StandardTopologyInputValue } from './topology';
@@ -65,7 +66,7 @@ export function importStandardClusterBuffers(
65
66
  const usage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
66
67
  const lightData = graph.importBuffer(
67
68
  'hdrp-light-data',
68
- { size: layout.lightDataSlotCount * 64, usage },
69
+ { size: layout.lightDataSlotCount * BYTES_PER_DIRECT_LIGHT_SLOT, usage },
69
70
  (frame) => resolveBuffers(frame, descriptor).lightDataBuffer,
70
71
  );
71
72
  if (!lightData.ok) return lightData;