@forgeax/engine-render 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/README.md +1374 -142
  2. package/dist/assembly/analytic-fog-registration.d.ts +3 -0
  3. package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
  4. package/dist/assembly/backend-contract.d.ts +2 -0
  5. package/dist/assembly/backend-contract.d.ts.map +1 -1
  6. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  7. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  8. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  9. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  10. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  11. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  12. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  13. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  15. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  16. package/dist/assembly/factory.d.ts +1 -1
  17. package/dist/assembly/factory.d.ts.map +1 -1
  18. package/dist/assembly/fxaa-registration.d.ts +4 -0
  19. package/dist/assembly/fxaa-registration.d.ts.map +1 -0
  20. package/dist/assembly/host-contract.d.ts +3 -3
  21. package/dist/assembly/host-contract.d.ts.map +1 -1
  22. package/dist/assembly/lod-observation.d.ts +4 -0
  23. package/dist/assembly/lod-observation.d.ts.map +1 -0
  24. package/dist/assembly/material/assembly.d.ts.map +1 -1
  25. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  26. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  27. package/dist/assembly/material-shader-policy.d.ts +16 -2
  28. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  29. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  30. package/dist/assembly/motion-blur-registration.d.ts +3 -0
  31. package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
  32. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  33. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  34. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  35. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  36. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  37. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  38. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  39. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  40. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  41. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  42. package/dist/assembly/renderer-inspection.d.ts +11 -0
  43. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  44. package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
  45. package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  47. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  48. package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
  49. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -1
  50. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  51. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  52. package/dist/assembly/webgpu-ready.d.ts +2 -2
  53. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  54. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  55. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  56. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  57. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  58. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  59. package/dist/authoring.mjs +1 -1
  60. package/dist/barrel-distortion.d.ts +47 -0
  61. package/dist/barrel-distortion.d.ts.map +1 -0
  62. package/dist/bloom-admission.d.ts +13 -0
  63. package/dist/bloom-admission.d.ts.map +1 -0
  64. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  65. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  66. package/dist/{chunk-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
  67. package/dist/chunk-HEB564WF.mjs.map +1 -0
  68. package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
  69. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  70. package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
  71. package/dist/{chunk-S665NJNF.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  72. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  73. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  74. package/dist/{chunk-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
  75. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  76. package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
  77. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  78. package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
  79. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  80. package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
  81. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  82. package/dist/cloud/density.d.ts +55 -0
  83. package/dist/cloud/density.d.ts.map +1 -0
  84. package/dist/cloud/extract.d.ts +25 -0
  85. package/dist/cloud/extract.d.ts.map +1 -0
  86. package/dist/cloud/feature.d.ts +57 -0
  87. package/dist/cloud/feature.d.ts.map +1 -0
  88. package/dist/cloud/frame-context.d.ts +8 -0
  89. package/dist/cloud/frame-context.d.ts.map +1 -0
  90. package/dist/cloud/inspection.d.ts +59 -0
  91. package/dist/cloud/inspection.d.ts.map +1 -0
  92. package/dist/cloud/optics.d.ts +56 -0
  93. package/dist/cloud/optics.d.ts.map +1 -0
  94. package/dist/cloud/parameters.d.ts +73 -0
  95. package/dist/cloud/parameters.d.ts.map +1 -0
  96. package/dist/cloud/resources.d.ts +60 -0
  97. package/dist/cloud/resources.d.ts.map +1 -0
  98. package/dist/cloud/shadow.d.ts +42 -0
  99. package/dist/cloud/shadow.d.ts.map +1 -0
  100. package/dist/cloud/temporal.d.ts +74 -0
  101. package/dist/cloud/temporal.d.ts.map +1 -0
  102. package/dist/components/atmosphere.d.ts +2 -0
  103. package/dist/components/atmosphere.d.ts.map +1 -1
  104. package/dist/components/barrel-distortion.d.ts +13 -0
  105. package/dist/components/barrel-distortion.d.ts.map +1 -0
  106. package/dist/components/camera.d.ts +20 -4
  107. package/dist/components/camera.d.ts.map +1 -1
  108. package/dist/components/cloud-layer.d.ts +29 -0
  109. package/dist/components/cloud-layer.d.ts.map +1 -0
  110. package/dist/components/index.d.ts +2 -0
  111. package/dist/components/index.d.ts.map +1 -1
  112. package/dist/components/instances.d.ts +20 -6
  113. package/dist/components/instances.d.ts.map +1 -1
  114. package/dist/components/mesh-filter.d.ts +6 -5
  115. package/dist/components/mesh-filter.d.ts.map +1 -1
  116. package/dist/components/motion-blur.d.ts +1 -0
  117. package/dist/components/motion-blur.d.ts.map +1 -1
  118. package/dist/construct-renderer.d.ts +1 -1
  119. package/dist/construct-renderer.d.ts.map +1 -1
  120. package/dist/construct-renderer.mjs +9751 -3528
  121. package/dist/construct-renderer.mjs.map +1 -1
  122. package/dist/device/gpu-residency.d.ts +6 -0
  123. package/dist/device/gpu-residency.d.ts.map +1 -1
  124. package/dist/dynamic-geometry.d.ts +5 -1
  125. package/dist/dynamic-geometry.d.ts.map +1 -1
  126. package/dist/environment/analytic-fog.d.ts +6 -0
  127. package/dist/environment/analytic-fog.d.ts.map +1 -0
  128. package/dist/errors/cloud.d.ts +59 -0
  129. package/dist/errors/cloud.d.ts.map +1 -0
  130. package/dist/errors/render.d.ts +23 -5
  131. package/dist/errors/render.d.ts.map +1 -1
  132. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  133. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  134. package/dist/extract/camera.d.ts.map +1 -1
  135. package/dist/extract/contracts.d.ts +12 -1
  136. package/dist/extract/contracts.d.ts.map +1 -1
  137. package/dist/extract/environment.d.ts +2 -0
  138. package/dist/extract/environment.d.ts.map +1 -1
  139. package/dist/features/barrel-distortion.d.ts +29 -0
  140. package/dist/features/barrel-distortion.d.ts.map +1 -0
  141. package/dist/features/error-reporting.d.ts +17 -0
  142. package/dist/features/error-reporting.d.ts.map +1 -0
  143. package/dist/features/host.d.ts +15 -0
  144. package/dist/features/host.d.ts.map +1 -1
  145. package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
  146. package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
  147. package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
  148. package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
  149. package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
  150. package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
  151. package/dist/features/plan.d.ts +15 -4
  152. package/dist/features/plan.d.ts.map +1 -1
  153. package/dist/features/prepared-gpu-work.d.ts +9 -5
  154. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  155. package/dist/features/render-graph-compute.d.ts.map +1 -1
  156. package/dist/features/render-graph-contribution.d.ts +5 -0
  157. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  158. package/dist/features/render-graph-raster.d.ts +1 -0
  159. package/dist/features/render-graph-raster.d.ts.map +1 -1
  160. package/dist/features/targets.d.ts +2 -0
  161. package/dist/features/targets.d.ts.map +1 -1
  162. package/dist/features/types.d.ts +44 -0
  163. package/dist/features/types.d.ts.map +1 -1
  164. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  165. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  166. package/dist/gpu-dirty-ranges.d.ts +11 -0
  167. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  168. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  169. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  170. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  171. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  172. package/dist/gpu-driven/prepared-draw.d.ts +7 -0
  173. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  174. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  175. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  176. package/dist/gpu-driven/production-raster.d.ts +50 -4
  177. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  178. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  179. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  180. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  181. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  182. package/dist/gpu-driven/view-gpu.d.ts +35 -2
  183. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  184. package/dist/gpu-scene.d.ts +11 -1
  185. package/dist/gpu-scene.d.ts.map +1 -1
  186. package/dist/hdrp-buffers.d.ts +2 -2
  187. package/dist/hdrp-buffers.d.ts.map +1 -1
  188. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  189. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  190. package/dist/index.d.ts +31 -8
  191. package/dist/index.d.ts.map +1 -1
  192. package/dist/index.mjs +258 -8
  193. package/dist/index.mjs.map +1 -1
  194. package/dist/inspection-types.d.ts +178 -3
  195. package/dist/inspection-types.d.ts.map +1 -1
  196. package/dist/instance-buffer-cache.d.ts +4 -4
  197. package/dist/instance-buffer-cache.d.ts.map +1 -1
  198. package/dist/instances.d.ts +49 -94
  199. package/dist/instances.d.ts.map +1 -1
  200. package/dist/internal.mjs +7 -7
  201. package/dist/pbr-pipeline.d.ts +19 -1
  202. package/dist/pbr-pipeline.d.ts.map +1 -1
  203. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  204. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  205. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  206. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  207. package/dist/pipeline/standard-output/types.d.ts +4 -2
  208. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  209. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  210. package/dist/pipeline/standard-post.d.ts +28 -19
  211. package/dist/pipeline/standard-post.d.ts.map +1 -1
  212. package/dist/pipeline-builder.d.ts +1 -1
  213. package/dist/pipeline-builder.d.ts.map +1 -1
  214. package/dist/pipeline-spec.d.ts +2 -2
  215. package/dist/plugin.d.ts.map +1 -1
  216. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  217. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  218. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  219. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  220. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  221. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  222. package/dist/record/fold-buckets.d.ts +95 -0
  223. package/dist/record/fold-buckets.d.ts.map +1 -0
  224. package/dist/record/fold-instance-buffer.d.ts +6 -0
  225. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  226. package/dist/record/frame-lighting.d.ts +1 -0
  227. package/dist/record/frame-lighting.d.ts.map +1 -1
  228. package/dist/record/frame-snapshot.d.ts +40 -3
  229. package/dist/record/frame-snapshot.d.ts.map +1 -1
  230. package/dist/record/frame-targets.d.ts.map +1 -1
  231. package/dist/record/frame.d.ts +14 -62
  232. package/dist/record/frame.d.ts.map +1 -1
  233. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  234. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  235. package/dist/record/gpu-timing.d.ts +8 -0
  236. package/dist/record/gpu-timing.d.ts.map +1 -1
  237. package/dist/record/main-pass-geometry.d.ts +21 -5
  238. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  239. package/dist/record/main-pass-material.d.ts +7 -1
  240. package/dist/record/main-pass-material.d.ts.map +1 -1
  241. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  242. package/dist/record/main-pass.d.ts +13 -2
  243. package/dist/record/main-pass.d.ts.map +1 -1
  244. package/dist/record/mesh-ssbo.d.ts +6 -5
  245. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  246. package/dist/record/motion-blur-receipt.d.ts +11 -0
  247. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  248. package/dist/record/probe-blend-buffer.d.ts +16 -0
  249. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  250. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  251. package/dist/record/render-context.d.ts +34 -31
  252. package/dist/record/render-context.d.ts.map +1 -1
  253. package/dist/record/shadow-pass.d.ts +2 -0
  254. package/dist/record/shadow-pass.d.ts.map +1 -1
  255. package/dist/record/skybox-post-pass.d.ts +6 -4
  256. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  257. package/dist/record/typed-frame-graph.d.ts +22 -2
  258. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  259. package/dist/record/view-ubo.d.ts +11 -3
  260. package/dist/record/view-ubo.d.ts.map +1 -1
  261. package/dist/record/volume-params.d.ts +9 -0
  262. package/dist/record/volume-params.d.ts.map +1 -0
  263. package/dist/recovery/render-system-candidate.d.ts +10 -0
  264. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  265. package/dist/reflection/record-owner.d.ts.map +1 -1
  266. package/dist/render-contract.d.ts +66 -8
  267. package/dist/render-contract.d.ts.map +1 -1
  268. package/dist/render-graph-primitives.d.ts.map +1 -1
  269. package/dist/render-pipeline.d.ts +106 -3
  270. package/dist/render-pipeline.d.ts.map +1 -1
  271. package/dist/render-system-extract-tail.d.ts +3 -2
  272. package/dist/render-system-extract-tail.d.ts.map +1 -1
  273. package/dist/render-system-extract.d.ts +24 -10
  274. package/dist/render-system-extract.d.ts.map +1 -1
  275. package/dist/render-system-presentation.d.ts +23 -0
  276. package/dist/render-system-presentation.d.ts.map +1 -0
  277. package/dist/render-system-producer-roots.d.ts +10 -0
  278. package/dist/render-system-producer-roots.d.ts.map +1 -0
  279. package/dist/render-system-residency.d.ts +12 -0
  280. package/dist/render-system-residency.d.ts.map +1 -0
  281. package/dist/render-system.d.ts +26 -15
  282. package/dist/render-system.d.ts.map +1 -1
  283. package/dist/scene/probe-blend.d.ts +27 -0
  284. package/dist/scene/probe-blend.d.ts.map +1 -1
  285. package/dist/scene/render-scene.d.ts +14 -5
  286. package/dist/scene/render-scene.d.ts.map +1 -1
  287. package/dist/ssao-buffers.d.ts +9 -0
  288. package/dist/ssao-buffers.d.ts.map +1 -1
  289. package/dist/surface/dynamic-input.d.ts +133 -0
  290. package/dist/surface/dynamic-input.d.ts.map +1 -0
  291. package/dist/surface/gpu-driven.d.ts +41 -0
  292. package/dist/surface/gpu-driven.d.ts.map +1 -0
  293. package/dist/surface/submission-observation.d.ts +136 -0
  294. package/dist/surface/submission-observation.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  296. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  297. package/dist/temporal/frame.d.ts +7 -0
  298. package/dist/temporal/frame.d.ts.map +1 -1
  299. package/dist/temporal/gpu.d.ts +13 -1
  300. package/dist/temporal/gpu.d.ts.map +1 -1
  301. package/dist/temporal/index.mjs +5 -5
  302. package/dist/temporal/inspection.d.ts.map +1 -1
  303. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  304. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  305. package/dist/temporal/view.d.ts +6 -1
  306. package/dist/temporal/view.d.ts.map +1 -1
  307. package/dist/transmission/single-layer-medium.d.ts +89 -0
  308. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  309. package/dist/typed-render-graph-primitives.d.ts +24 -9
  310. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  311. package/dist/volume/component.d.ts +9 -5
  312. package/dist/volume/component.d.ts.map +1 -1
  313. package/dist/volume/extract.d.ts +1 -1
  314. package/dist/volume/extract.d.ts.map +1 -1
  315. package/dist/volume/inspection.d.ts +2 -0
  316. package/dist/volume/inspection.d.ts.map +1 -1
  317. package/dist/volume/passes.d.ts +4 -1
  318. package/dist/volume/passes.d.ts.map +1 -1
  319. package/dist/volume/resources.d.ts.map +1 -1
  320. package/dist/volume/temporal.d.ts +3 -1
  321. package/dist/volume/temporal.d.ts.map +1 -1
  322. package/package.json +22 -21
  323. package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
  324. package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
  325. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  326. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  327. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  328. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  329. package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
  330. package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
  331. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  332. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  333. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  334. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  335. package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
  336. package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
  337. package/src/__tests__/environment-selection.unit.test.ts +12 -0
  338. package/src/__tests__/factory-contract.integration.test.ts +626 -113
  339. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  340. package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
  341. package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +2 -1
  347. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  348. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  349. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  350. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +7 -6
  351. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
  352. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
  353. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  354. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  355. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  356. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  357. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  358. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  359. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  360. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
  361. package/src/__tests__/gpu-scene.unit.test.ts +210 -9
  362. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  363. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  364. package/src/__tests__/instances-store.unit.test.ts +105 -238
  365. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  366. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  367. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  368. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  369. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
  370. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  371. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  372. package/src/__tests__/motion-blur-compute.dawn.test.ts +589 -0
  373. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  374. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  375. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  376. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  377. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
  378. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  379. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
  380. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  381. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  382. package/src/__tests__/public-surface.test-d.ts +8 -0
  383. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  384. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  385. package/src/__tests__/render-error-code-owner.test-d.ts +9 -0
  386. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  387. package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
  388. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  389. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  390. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
  391. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  392. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  393. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +37 -6
  394. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  395. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  396. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  397. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  398. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  399. package/src/__tests__/renderer-frame-transaction.integration.test.ts +33 -11
  400. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  401. package/src/__tests__/shader-manifest-fixture.ts +4 -4
  402. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  403. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  404. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  405. package/src/__tests__/skinned-shadow-caster.test.ts +17 -0
  406. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  407. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  408. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  409. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  410. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  411. package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
  412. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  413. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  414. package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
  415. package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
  416. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  417. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  418. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  419. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  420. package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
  421. package/src/__tests__/temporal-view.unit.test.ts +2 -1
  422. package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
  423. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  424. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  425. package/src/__tests__/volume-optics-oracle.unit.test.ts +7 -3
  426. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
  427. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  428. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  429. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  430. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +558 -68
  431. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
  432. package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
  433. package/src/assembly/analytic-fog-registration.ts +14 -0
  434. package/src/assembly/backend-contract.ts +30 -0
  435. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  436. package/src/assembly/canvas-draw-guard.ts +11 -0
  437. package/src/assembly/cloud-shadow-entry.ts +22 -0
  438. package/src/assembly/dynamic-geometry-host.ts +65 -37
  439. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  440. package/src/assembly/factory.ts +2 -30
  441. package/src/assembly/fxaa-registration.ts +17 -0
  442. package/src/assembly/host-contract.ts +3 -3
  443. package/src/assembly/lod-observation.ts +12 -0
  444. package/src/assembly/material/assembly.ts +25 -13
  445. package/src/assembly/material/pipeline-helpers.ts +53 -12
  446. package/src/assembly/material-shader-policy.ts +55 -0
  447. package/src/assembly/material-shader-prewarm.ts +21 -10
  448. package/src/assembly/motion-blur-registration.ts +17 -0
  449. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  450. package/src/assembly/recovery/renderer-recover.ts +41 -18
  451. package/src/assembly/render-feature-post-processes.ts +54 -0
  452. package/src/assembly/renderer-facade.ts +6 -1
  453. package/src/assembly/renderer-feature-inspection.ts +8 -2
  454. package/src/assembly/renderer-frame-transaction.ts +23 -0
  455. package/src/assembly/renderer-inspection.ts +28 -0
  456. package/src/assembly/skin-palette-owner.ts +1 -1
  457. package/src/assembly/temporal-post-process-prewarm.ts +40 -0
  458. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  459. package/src/assembly/webgpu-ready-contract.ts +8 -3
  460. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  461. package/src/assembly/webgpu-ready.ts +296 -306
  462. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  463. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  464. package/src/assembly/webgpu-renderer.ts +228 -281
  465. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  466. package/src/barrel-distortion.ts +247 -0
  467. package/src/bloom-admission.ts +21 -0
  468. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  469. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  470. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  471. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  472. package/src/cloud/density.ts +600 -0
  473. package/src/cloud/extract.ts +110 -0
  474. package/src/cloud/feature.ts +1810 -0
  475. package/src/cloud/frame-context.ts +42 -0
  476. package/src/cloud/inspection.ts +130 -0
  477. package/src/cloud/optics.ts +285 -0
  478. package/src/cloud/parameters.ts +255 -0
  479. package/src/cloud/resources.ts +122 -0
  480. package/src/cloud/shadow.ts +167 -0
  481. package/src/cloud/temporal.ts +226 -0
  482. package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
  483. package/src/components/atmosphere.ts +4 -0
  484. package/src/components/barrel-distortion.ts +46 -0
  485. package/src/components/camera.ts +66 -10
  486. package/src/components/cloud-layer.ts +47 -0
  487. package/src/components/index.ts +2 -0
  488. package/src/components/instances.ts +18 -45
  489. package/src/components/mesh-filter.ts +11 -9
  490. package/src/components/motion-blur.ts +1 -0
  491. package/src/components/sprite-instances.ts +1 -1
  492. package/src/construct-renderer.ts +1 -1
  493. package/src/device/gpu-residency.ts +56 -12
  494. package/src/dynamic-geometry.ts +12 -1
  495. package/src/environment/analytic-fog.ts +44 -0
  496. package/src/environment/background.ts +2 -2
  497. package/src/errors/cloud.ts +103 -0
  498. package/src/errors/render.ts +58 -8
  499. package/src/examples/single-layer-medium-surface.ts +59 -0
  500. package/src/extract/camera.ts +35 -8
  501. package/src/extract/contracts.ts +12 -0
  502. package/src/extract/environment.ts +4 -0
  503. package/src/features/barrel-distortion.ts +172 -0
  504. package/src/features/error-reporting.ts +98 -0
  505. package/src/features/host.ts +138 -24
  506. package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
  507. package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
  508. package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
  509. package/src/features/motion-blur/motion-blur-params.ts +70 -2
  510. package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
  511. package/src/features/plan.ts +33 -8
  512. package/src/features/prepared-gpu-work.ts +86 -35
  513. package/src/features/render-graph-compute.ts +13 -5
  514. package/src/features/render-graph-contribution.ts +11 -0
  515. package/src/features/render-graph-raster.ts +45 -3
  516. package/src/features/targets.ts +66 -0
  517. package/src/features/types.ts +47 -0
  518. package/src/fullscreen-post-process-pass.ts +41 -9
  519. package/src/gpu-dirty-ranges.ts +48 -0
  520. package/src/gpu-driven/batch-topology.ts +53 -0
  521. package/src/gpu-driven/material-artifacts.ts +35 -32
  522. package/src/gpu-driven/prepared-draw.ts +27 -14
  523. package/src/gpu-driven/production-raster-material.ts +1894 -0
  524. package/src/gpu-driven/production-raster.ts +904 -787
  525. package/src/gpu-driven/resource-allocation.ts +142 -0
  526. package/src/gpu-driven/shadow-ownership.ts +71 -0
  527. package/src/gpu-driven/view-gpu.ts +181 -10
  528. package/src/gpu-scene.ts +259 -101
  529. package/src/hdrp-buffers.ts +4 -3
  530. package/src/ibl/skylight-bind-group.ts +49 -7
  531. package/src/index.ts +228 -9
  532. package/src/inspection-types.ts +222 -2
  533. package/src/instance-buffer-cache.ts +4 -4
  534. package/src/instances.ts +151 -492
  535. package/src/pbr-pipeline.ts +219 -13
  536. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  537. package/src/pipeline/standard-forward-lane.ts +313 -57
  538. package/src/pipeline/standard-output/graph.ts +8 -2
  539. package/src/pipeline/standard-output/types.ts +12 -1
  540. package/src/pipeline/standard-pipeline.ts +291 -18
  541. package/src/pipeline/standard-post.ts +397 -102
  542. package/src/pipeline-builder.ts +1 -1
  543. package/src/pipeline-spec.ts +5 -5
  544. package/src/plugin.ts +4 -0
  545. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  546. package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
  547. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  548. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  549. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  550. package/src/record/__tests__/temporal-payload.unit.test.ts +3 -2
  551. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  552. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  553. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  554. package/src/record/barrel-distortion-frame.ts +110 -0
  555. package/src/record/dynamic-geometry-consumption.ts +39 -9
  556. package/src/record/fold-buckets.ts +852 -0
  557. package/src/record/fold-instance-buffer.ts +51 -0
  558. package/src/record/frame-lighting.ts +36 -2
  559. package/src/record/frame-snapshot.ts +44 -4
  560. package/src/record/frame-targets.ts +10 -6
  561. package/src/record/frame.ts +373 -1099
  562. package/src/record/gpu-draw-receipts.ts +38 -0
  563. package/src/record/gpu-timing.ts +48 -5
  564. package/src/record/main-pass-geometry.ts +281 -83
  565. package/src/record/main-pass-material.ts +66 -4
  566. package/src/record/main-pass-sprite-draws.ts +13 -66
  567. package/src/record/main-pass.ts +156 -20
  568. package/src/record/mesh-ssbo.ts +43 -6
  569. package/src/record/motion-blur-receipt.ts +91 -0
  570. package/src/record/probe-blend-buffer.ts +180 -0
  571. package/src/record/recovery-pipeline.ts +35 -3
  572. package/src/record/render-context.ts +51 -31
  573. package/src/record/shadow-pass.ts +36 -2
  574. package/src/record/skybox-post-pass.ts +150 -200
  575. package/src/record/typed-frame-graph.ts +824 -44
  576. package/src/record/view-ubo.ts +26 -3
  577. package/src/record/volume-params.ts +225 -0
  578. package/src/recovery/render-system-candidate.ts +257 -52
  579. package/src/reflection/record-owner.ts +7 -3
  580. package/src/render-contract.ts +71 -8
  581. package/src/render-graph-primitives.ts +7 -1
  582. package/src/render-pipeline.ts +136 -1
  583. package/src/render-system-extract-tail.ts +72 -60
  584. package/src/render-system-extract.ts +117 -87
  585. package/src/render-system-presentation.ts +56 -0
  586. package/src/render-system-producer-roots.ts +96 -0
  587. package/src/render-system-residency.ts +159 -0
  588. package/src/render-system.ts +601 -482
  589. package/src/scene/probe-blend.ts +96 -4
  590. package/src/scene/render-scene.ts +431 -281
  591. package/src/ssao-buffers.ts +95 -2
  592. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  593. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  594. package/src/surface/dynamic-input.ts +658 -0
  595. package/src/surface/gpu-driven.ts +147 -0
  596. package/src/surface/submission-observation.ts +517 -0
  597. package/src/systems/skin-palette-allocator.ts +4 -1
  598. package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
  599. package/src/temporal/frame-coordinator.ts +8 -1
  600. package/src/temporal/frame.ts +20 -0
  601. package/src/temporal/gpu.ts +101 -17
  602. package/src/temporal/inspection.ts +7 -1
  603. package/src/temporal/standard-scene-data.ts +5 -0
  604. package/src/temporal/target-coverage-attachment.ts +4 -0
  605. package/src/temporal/view.ts +13 -2
  606. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  607. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  608. package/src/transmission/single-layer-medium.ts +322 -0
  609. package/src/typed-render-graph-primitives.ts +191 -50
  610. package/src/volume/component.ts +10 -10
  611. package/src/volume/extract.ts +11 -5
  612. package/src/volume/inspection.ts +3 -0
  613. package/src/volume/passes.ts +95 -8
  614. package/src/volume/resources.ts +2 -1
  615. package/src/volume/temporal.ts +11 -0
  616. package/dist/chunk-4NNZQCL3.mjs.map +0 -1
  617. package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
  618. package/dist/chunk-DRR7D3KX.mjs.map +0 -1
  619. package/dist/chunk-GWCEMDVR.mjs.map +0 -1
  620. package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
  621. package/dist/chunk-JRIPCMYC.mjs.map +0 -1
  622. package/dist/chunk-LULCA3OF.mjs +0 -1713
  623. package/dist/chunk-LULCA3OF.mjs.map +0 -1
  624. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/device/device-scope.ts","../src/gpu-usage.ts","../src/prepare/extended-lighting/resources.ts","../src/record/frame-snapshot.ts","../src/temporal/coverage.ts","../src/gpu-stage.ts","../src/pbr-pipeline.ts","../src/scene/probe-blend-record.ts","../src/targets/material-source.ts","../src/systems/pass-selector.ts","../src/gpu-driven/prepared-draw.ts","../src/extract/gpu-driven.ts"],"names":["index","input"],"mappings":"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","file":"chunk-DRR7D3KX.mjs","sourcesContent":["import { err, ok, type Result } from '@forgeax/engine-types';\nimport { LifecycleConstructionError } from '../errors/render';\nimport type { DeviceResourceKind, DeviceScopeReceipt } from './resource-types';\n\nexport {\n DEVICE_RESOURCE_KINDS,\n type DeviceResourceKind,\n type DeviceScopeReceipt,\n} from './resource-types';\n\nexport type DeviceScopeState = 'active' | 'retiring' | 'retired' | 'abandoned' | 'disposed';\n\nexport interface ResourceRef<T> {\n readonly kind: DeviceResourceKind;\n readonly owner: string;\n readonly generation: number;\n readonly value: T;\n isCurrent(scope: DeviceScope): boolean;\n isStale(scope: DeviceScope): boolean;\n}\n\nexport class DeviceResourceRef<T> implements ResourceRef<T> {\n readonly kind: DeviceResourceKind;\n readonly owner: string;\n readonly generation: number;\n readonly value: T;\n\n constructor(kind: DeviceResourceKind, owner: string, generation: number, value: T) {\n this.kind = kind;\n this.owner = owner;\n this.generation = generation;\n this.value = value;\n }\n\n isCurrent(scope: DeviceScope): boolean {\n return scope.accepts(this);\n }\n\n isStale(scope: DeviceScope): boolean {\n return !this.isCurrent(scope);\n }\n}\n\ninterface OwnedResource {\n readonly ref: DeviceResourceRef<unknown>;\n readonly cleanup: (value: unknown) => void | Promise<void>;\n}\n\nfunction idempotentCleanup<T>(\n cleanup: (value: T) => void | Promise<void>,\n): (value: T) => void | Promise<void> {\n let cleaned = false;\n return (value: T) => {\n if (cleaned) return;\n cleaned = true;\n return cleanup(value);\n };\n}\n\nexport class DeviceScope {\n readonly generation: number;\n readonly owner: string;\n readonly parent: DeviceScope | undefined;\n private lifecycleState: DeviceScopeState = 'active';\n private readonly resources = new Map<ResourceRef<unknown>, OwnedResource>();\n private readonly children: DeviceScope[] = [];\n\n private constructor(generation: number, owner: string, parent?: DeviceScope) {\n this.generation = generation;\n this.owner = owner;\n this.parent = parent;\n parent?.children.push(this);\n }\n\n static create(generation: number, owner: string): DeviceScope {\n if (!Number.isSafeInteger(generation) || generation < 0) {\n throw new RangeError('DeviceScope generation must be a non-negative safe integer.');\n }\n if (owner.length === 0) throw new TypeError('DeviceScope owner must not be empty.');\n return new DeviceScope(generation, owner);\n }\n\n get state(): DeviceScopeState {\n return this.lifecycleState;\n }\n\n get childrenSnapshot(): readonly DeviceScope[] {\n return [...this.children];\n }\n\n /** Create a renderer-owned child scope without exposing a second device owner. */\n createChild(owner: string): DeviceScope {\n if (this.lifecycleState !== 'active') {\n throw new Error('Cannot create a child DeviceScope from an inactive scope.');\n }\n if (owner.length === 0) throw new TypeError('DeviceScope child owner must not be empty.');\n return new DeviceScope(this.generation, owner, this);\n }\n\n ref<T>(kind: DeviceResourceKind, value: T): ResourceRef<T> {\n const ref = new DeviceResourceRef(kind, this.owner, this.generation, value);\n this.resources.set(ref, { ref, cleanup: () => undefined });\n return ref;\n }\n\n accepts(ref: ResourceRef<unknown>): boolean {\n return (\n this.lifecycleState === 'active' &&\n ref.owner === this.owner &&\n ref.generation === this.generation\n );\n }\n\n isAlive(): boolean {\n return this.lifecycleState === 'active';\n }\n\n resourceDelta(): number {\n return this.resources.size;\n }\n\n /** @internal */\n _adopt<T>(\n kind: DeviceResourceKind,\n value: T,\n cleanup: (value: T) => void | Promise<void>,\n ): ResourceRef<T> {\n const ref = new DeviceResourceRef(kind, this.owner, this.generation, value);\n this.resources.set(ref, {\n ref,\n cleanup: idempotentCleanup(cleanup) as (resource: unknown) => void | Promise<void>,\n });\n return ref;\n }\n\n /** @internal Remove ownership only after the resource's cleanup succeeded. */\n _release(ref: ResourceRef<unknown>): void {\n this.resources.delete(ref);\n }\n\n /** @internal */\n _clearResources(): OwnedResource[] {\n const resources = [...this.resources.values()];\n this.resources.clear();\n for (const resource of resources.reverse()) {\n try {\n const pending = resource.cleanup(resource.ref.value);\n if (pending instanceof Promise) void pending.catch(() => undefined);\n } catch {\n // Synchronous scope termination is bounded; transaction cleanup owns\n // structured failure collection during construction and replacement.\n }\n }\n return resources;\n }\n\n /** Mark an active child as retiring without releasing in-flight resources. */\n beginRetire(): void {\n if (this.lifecycleState === 'active') this.lifecycleState = 'retiring';\n }\n\n private clearChildren(): void {\n for (const child of [...this.children].reverse()) {\n child.retire();\n }\n }\n\n private detachChild(child: DeviceScope): void {\n const index = this.children.indexOf(child);\n if (index >= 0) this.children.splice(index, 1);\n }\n\n retire(): void {\n if (this.lifecycleState !== 'active' && this.lifecycleState !== 'retiring') return;\n this.lifecycleState = 'retiring';\n this.clearChildren();\n this._clearResources();\n this.lifecycleState = 'retired';\n }\n\n abandon(): void {\n if (this.lifecycleState !== 'active') return;\n this.lifecycleState = 'abandoned';\n this.clearChildren();\n this._clearResources();\n }\n\n dispose(): void {\n if (this.lifecycleState === 'disposed') return;\n this.lifecycleState = 'disposed';\n this.clearChildren();\n this._clearResources();\n }\n\n async replace(\n generation: number,\n resources: readonly LifecycleResourceSpec<unknown>[],\n ): Promise<LifecycleResult> {\n const replacement = new DeviceScope(generation, this.owner, this);\n const transaction = new LifecycleTransaction(replacement);\n for (const resource of resources) transaction.add(resource);\n const result = await transaction.commit();\n if (!result.ok) {\n replacement.abandon();\n return result;\n }\n if (!this.isAlive()) {\n replacement.dispose();\n return transaction.failure('dispose');\n }\n // The replacement is now the new owner. Detach it before retiring the\n // old parent so parent cleanup cannot retire the just-published child.\n this.detachChild(replacement);\n this.retire();\n return ok(replacement);\n }\n\n /** @internal */\n _receipt(): DeviceScopeReceipt {\n return {\n owner: this.owner,\n generation: this.generation,\n resourceCount: this.resources.size,\n };\n }\n}\n\nexport interface LifecycleResourceSpec<T> {\n readonly kind: DeviceResourceKind;\n readonly create: () => T | Promise<T>;\n readonly cleanup: (value: T) => void | Promise<void>;\n}\n\nexport interface LifecycleCleanupFailure {\n readonly resourceKind: DeviceResourceKind;\n readonly cause: unknown;\n}\n\nexport interface LifecycleFailure {\n readonly primary: LifecycleConstructionError;\n readonly cleanupFailures: readonly LifecycleCleanupFailure[];\n readonly receipt: DeviceScopeReceipt;\n}\n\nexport type LifecycleResult = Result<DeviceScope, LifecycleFailure>;\n\nexport interface LifecycleTransactionOptions {\n readonly failureAt?: number;\n}\n\ninterface CreatedResource {\n readonly spec: LifecycleResourceSpec<unknown>;\n readonly value: unknown;\n readonly cleanup: (value: unknown) => void | Promise<void>;\n}\n\nexport class LifecycleTransaction {\n private readonly resources: LifecycleResourceSpec<unknown>[] = [];\n private readonly options: LifecycleTransactionOptions;\n private committed = false;\n\n constructor(\n private readonly scope: DeviceScope,\n options: LifecycleTransactionOptions = {},\n ) {\n this.options = options;\n }\n\n add<T>(spec: LifecycleResourceSpec<T>): this {\n if (this.committed) throw new Error('LifecycleTransaction is already committed.');\n this.resources.push(spec as LifecycleResourceSpec<unknown>);\n return this;\n }\n\n async commit(): Promise<LifecycleResult> {\n if (this.committed) return this.failure('create');\n this.committed = true;\n const created: CreatedResource[] = [];\n for (let index = 0; index < this.resources.length; index += 1) {\n const spec = this.resources[index];\n if (spec === undefined) continue;\n try {\n if (this.options.failureAt === index + 1) {\n throw new Error(`injected lifecycle failure at ${index + 1}`);\n }\n const value = await spec.create();\n if (!this.scope.isAlive()) {\n await this.cleanupOne(value, created, idempotentCleanup(spec.cleanup));\n return this.failure('dispose');\n }\n created.push({ spec, value, cleanup: idempotentCleanup(spec.cleanup) });\n } catch (cause) {\n const cleanupFailures = await this.cleanupCreated(created);\n return this.failure('create', spec.kind, cleanupFailures, cause);\n }\n }\n if (!this.scope.isAlive()) {\n const cleanupFailures = await this.cleanupCreated(created);\n return this.failure('dispose', this.resources.at(-1)?.kind ?? 'listener', cleanupFailures);\n }\n for (const item of created) this.scope._adopt(item.spec.kind, item.value, item.spec.cleanup);\n return ok(this.scope);\n }\n\n failure(\n operation: 'create' | 'dispose',\n resourceKind: DeviceResourceKind = this.resources.at(-1)?.kind ?? 'listener',\n cleanupFailures: readonly LifecycleCleanupFailure[] = [],\n cause: unknown = undefined,\n ): LifecycleResult {\n return err({\n primary: new LifecycleConstructionError({\n owner: this.scope.owner,\n generation: this.scope.generation,\n operation,\n resourceKind,\n cause,\n cleanupFailures,\n receipt: this.scope._receipt(),\n }),\n cleanupFailures,\n receipt: this.scope._receipt(),\n });\n }\n\n private async cleanupCreated(\n created: readonly CreatedResource[],\n ): Promise<LifecycleCleanupFailure[]> {\n const failures: LifecycleCleanupFailure[] = [];\n for (let index = created.length - 1; index >= 0; index -= 1) {\n const item = created[index];\n if (item === undefined) continue;\n try {\n await item.cleanup(item.value);\n } catch (cause) {\n failures.push({ resourceKind: item.spec.kind, cause });\n }\n }\n return failures;\n }\n\n private async cleanupOne(\n value: unknown,\n created: readonly CreatedResource[],\n cleanup: (value: unknown) => void | Promise<void>,\n ): Promise<void> {\n await this.cleanupCreated(created);\n try {\n await cleanup(value);\n } catch {\n // The terminal dispose result is intentionally bounded; prior cleanup\n // evidence remains in the transaction failure shape.\n }\n }\n}\n","// @forgeax/engine-runtime - render package GPU buffer usage values.\n//\n// Keep the WebGPU bit values in one dependency-free owner because the render\n// package also runs against the null and WebGL2-compatible RHI shims where the\n// browser's GPUBufferUsage global is unavailable.\n\nexport const GPU_BUFFER_USAGE_VERTEX = 0x20;\nexport const GPU_BUFFER_USAGE_INDEX = 0x10;\nexport const GPU_BUFFER_USAGE_COPY_DST = 0x08;\nexport const GPU_BUFFER_USAGE_COPY_SRC = 0x04;\nexport const GPU_BUFFER_USAGE_UNIFORM = 0x40;\nexport const GPU_BUFFER_USAGE_STORAGE = 0x80;\nexport const GPU_BUFFER_USAGE_INDIRECT = 0x100;\nexport const GPU_BUFFER_USAGE_MAP_READ = 0x01;\nexport const GPU_BUFFER_USAGE_QUERY_RESOLVE = 0x200;\n","import type { Buffer, Result, RhiDevice, Sampler, Texture } from '@forgeax/engine-rhi';\nimport { RhiError } from '@forgeax/engine-rhi';\nimport { err, ok } from '@forgeax/engine-types';\nimport type { DeviceScope } from '../../device/device-scope';\nimport { LifecycleTransaction } from '../../device/lifecycle-transaction';\nimport {\n GPU_TEXTURE_USAGE_COPY_DST,\n GPU_TEXTURE_USAGE_TEXTURE_BINDING,\n} from '../../gpu-texture-usage';\nimport { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from '../../gpu-usage';\n\nexport const EXTENDED_LIGHTING_TOPOLOGY = 'extendedLighting' as const;\nexport const IES_SLICE_CAPACITY = 32;\nexport const COOKIE_SLICE_CAPACITY = 32;\nexport const PROBE_RECORD_CAPACITY = 64;\nexport const IES_SLICE_WIDTH = 256;\nexport const IES_SLICE_HEIGHT = 128;\nexport const COOKIE_SLICE_SIZE = 256;\nexport const COOKIE_MATRIX_BYTES = 32 * 16 * Float32Array.BYTES_PER_ELEMENT;\n/**\n * Minimum per-stage sampled-texture limit for the shared PBR + extended-\n * lighting pipeline-layout topology. The current BGL closure reserves 19\n * sampled textures for the URP path and 21 for the HDRP/Probe path after the\n * material IBL and transmission injections; WebGPU validates this pipeline-\n * layout count even when a compiled shader variant does not read every\n * optional entry.\n */\nexport const EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES = 21;\n\n/**\n * Keep shader-variant selection and resource admission on one capability fact.\n * An omitted limit is treated as unavailable: a caller must not claim the\n * extended topology without a numeric device limit proving it fits.\n */\nexport function extendedLightingSampledTextureCapacityAvailable(\n maxSampledTexturesPerShaderStage: number | undefined,\n): boolean {\n return (\n maxSampledTexturesPerShaderStage !== undefined &&\n maxSampledTexturesPerShaderStage >= EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES\n );\n}\n\nexport interface ExtendedLightingCapabilityResult {\n readonly admitted: boolean;\n readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;\n readonly reason: string | undefined;\n}\n\nexport interface ExtendedLightingResourceInput {\n readonly device: RhiDevice | undefined;\n readonly scope: DeviceScope;\n readonly iesSliceCount: number;\n readonly cookieSliceCount: number;\n readonly cookieMatrices: number;\n readonly iesData?: Uint8Array | undefined;\n readonly cookieData?: Uint8Array | undefined;\n readonly cookieMatrixData?: Float32Array | undefined;\n}\n\nexport interface ExtendedLightingResourceCandidate {\n readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;\n readonly generation: number;\n readonly scope: DeviceScope;\n readonly iesSliceCount: number;\n readonly cookieSliceCount: number;\n readonly cookieMatrices: number;\n readonly sampler: Sampler;\n readonly iesTexture: Texture | undefined;\n readonly cookieTexture: Texture | undefined;\n readonly cookieMatrixBuffer: Buffer | undefined;\n readonly descriptorBytes: number;\n readonly uploadCount: number;\n}\n\nexport interface ExtendedLightingResourceInspection {\n readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;\n readonly generation: number;\n readonly status: 'empty' | 'candidate' | 'accepted';\n readonly accepted: boolean;\n readonly resourceCount: number;\n readonly descriptorBytes: number;\n readonly uploadCount: number;\n readonly blendInvalidations: number;\n readonly passCount: number;\n}\n\nfunction failure(expected: string, actual: string): Result<never, RhiError> {\n return err(\n new RhiError({\n code: 'webgpu-runtime-error',\n expected,\n hint: 'repair the extended lighting resource facts and retry the candidate generation',\n detail: { error: { code: 'extended-lighting-resource', message: actual } },\n }),\n );\n}\n\nfunction validCount(value: number, capacity: number): boolean {\n return Number.isSafeInteger(value) && value >= 0 && value <= capacity;\n}\n\n/** Derive admission from the RHI facts; no backend-kind policy is involved. */\nexport function deriveExtendedLightingCapability(\n device: Pick<RhiDevice, 'caps' | 'limits'>,\n): ExtendedLightingCapabilityResult {\n const maxSampledTextures = device.limits.maxSampledTexturesPerShaderStage;\n if (!extendedLightingSampledTextureCapacityAvailable(maxSampledTextures)) {\n return {\n admitted: false,\n topology: EXTENDED_LIGHTING_TOPOLOGY,\n reason: `maxSampledTexturesPerShaderStage ${maxSampledTextures ?? 0} < ${EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES}`,\n };\n }\n const maxLayers = device.limits.maxTextureArrayLayers ?? 0;\n const maxUniformBuffers = device.limits.maxUniformBuffersPerShaderStage ?? 0;\n if (maxLayers < IES_SLICE_CAPACITY) {\n return {\n admitted: false,\n topology: EXTENDED_LIGHTING_TOPOLOGY,\n reason: `maxTextureArrayLayers ${maxLayers} < ${IES_SLICE_CAPACITY}`,\n };\n }\n if (maxUniformBuffers < 1) {\n return {\n admitted: false,\n topology: EXTENDED_LIGHTING_TOPOLOGY,\n reason: `maxUniformBuffersPerShaderStage ${maxUniformBuffers} < 1`,\n };\n }\n if (\n !device.caps.storageBuffer ||\n !device.caps.rgba16floatRenderable ||\n !device.caps.samplerAliasing\n ) {\n return {\n admitted: false,\n topology: EXTENDED_LIGHTING_TOPOLOGY,\n reason: 'required storage-buffer, rgba16float, or sampler capability is unavailable',\n };\n }\n return { admitted: true, topology: EXTENDED_LIGHTING_TOPOLOGY, reason: undefined };\n}\n\nfunction createTexture(\n device: RhiDevice,\n label: string,\n format: 'r16float' | 'rgba8unorm',\n width: number,\n height: number,\n layers: number,\n): Result<Texture, RhiError> {\n return device.createTexture({\n label,\n size: { width, height, depthOrArrayLayers: layers },\n mipLevelCount: 1,\n sampleCount: 1,\n dimension: '2d',\n format,\n usage: GPU_TEXTURE_USAGE_COPY_DST | GPU_TEXTURE_USAGE_TEXTURE_BINDING,\n viewFormats: [],\n textureBindingViewDimension: undefined,\n });\n}\n\nfunction requireResource<T>(result: Result<T, RhiError>): T {\n if (!result.ok) throw result.error;\n return result.value;\n}\n\nfunction writeTextureSlices(\n device: RhiDevice,\n texture: Texture,\n data: Uint8Array | undefined,\n bytesPerRow: number,\n height: number,\n layerCount: number,\n width: number,\n): number {\n if (data === undefined || layerCount === 0) return 0;\n const bytesPerSlice = bytesPerRow * height;\n const requiredBytes = bytesPerSlice * layerCount;\n if (data.byteLength < requiredBytes) {\n throw new Error(`extended lighting texture upload requires ${requiredBytes} bytes`);\n }\n for (let layer = 0; layer < layerCount; layer += 1) {\n const start = layer * bytesPerSlice;\n requireResource(\n device.queue.writeTexture(\n { texture, mipLevel: 0, origin: { x: 0, y: 0, z: layer } },\n data.subarray(start, start + bytesPerSlice),\n { offset: 0, bytesPerRow, rowsPerImage: height },\n { width, height, depthOrArrayLayers: 1 },\n ),\n );\n }\n return layerCount;\n}\n\n/** Build a complete candidate; nothing is adopted until the transaction commits. */\nexport async function createExtendedLightingResourceCandidate(\n input: ExtendedLightingResourceInput,\n): Promise<Result<ExtendedLightingResourceCandidate, RhiError>> {\n const { device, scope } = input;\n if (device === undefined) return failure('a live RHI device is required', 'device is undefined');\n if (!validCount(input.iesSliceCount, IES_SLICE_CAPACITY)) {\n return failure(`IES slice count <= ${IES_SLICE_CAPACITY}`, String(input.iesSliceCount));\n }\n if (!validCount(input.cookieSliceCount, COOKIE_SLICE_CAPACITY)) {\n return failure(\n `Cookie slice count <= ${COOKIE_SLICE_CAPACITY}`,\n String(input.cookieSliceCount),\n );\n }\n if (!validCount(input.cookieMatrices, COOKIE_SLICE_CAPACITY)) {\n return failure(`Cookie matrix count <= ${COOKIE_SLICE_CAPACITY}`, String(input.cookieMatrices));\n }\n const capability = deriveExtendedLightingCapability(device);\n if (!capability.admitted)\n return failure('extendedLighting capability admission', capability.reason ?? 'unavailable');\n if (\n input.cookieMatrixData !== undefined &&\n input.cookieMatrixData.byteLength < input.cookieMatrices * 16 * Float32Array.BYTES_PER_ELEMENT\n ) {\n return failure(\n 'cookie matrix upload payload',\n `requires ${input.cookieMatrices * 16 * Float32Array.BYTES_PER_ELEMENT} bytes`,\n );\n }\n\n const transaction = new LifecycleTransaction(scope);\n let iesTexture: Texture | undefined;\n let cookieTexture: Texture | undefined;\n let cookieMatrixBuffer: Buffer | undefined;\n let sampler: Sampler | undefined;\n let uploadCount = 0;\n transaction.add({\n kind: 'texture',\n create: () => {\n const created = requireResource(\n createTexture(\n device,\n 'extended-lighting-ies',\n 'r16float',\n IES_SLICE_WIDTH,\n IES_SLICE_HEIGHT,\n IES_SLICE_CAPACITY,\n ),\n );\n uploadCount += writeTextureSlices(\n device,\n created,\n input.iesData,\n IES_SLICE_WIDTH * 2,\n IES_SLICE_HEIGHT,\n input.iesSliceCount,\n IES_SLICE_WIDTH,\n );\n iesTexture = created;\n return created;\n },\n cleanup: (value) => {\n const destroyed = device.destroyTexture(value);\n if (!destroyed.ok) throw destroyed.error;\n },\n });\n transaction.add({\n kind: 'texture',\n create: () => {\n const created = requireResource(\n createTexture(\n device,\n 'extended-lighting-cookie',\n 'rgba8unorm',\n COOKIE_SLICE_SIZE,\n COOKIE_SLICE_SIZE,\n COOKIE_SLICE_CAPACITY,\n ),\n );\n uploadCount += writeTextureSlices(\n device,\n created,\n input.cookieData,\n COOKIE_SLICE_SIZE * 4,\n COOKIE_SLICE_SIZE,\n input.cookieSliceCount,\n COOKIE_SLICE_SIZE,\n );\n cookieTexture = created;\n return created;\n },\n cleanup: (value) => {\n const destroyed = device.destroyTexture(value);\n if (!destroyed.ok) throw destroyed.error;\n },\n });\n transaction.add({\n kind: 'buffer',\n create: () => {\n const created = requireResource(\n device.createBuffer({\n label: 'extended-lighting-cookie-matrices',\n size: COOKIE_MATRIX_BYTES,\n usage: GPU_BUFFER_USAGE_COPY_DST | GPU_BUFFER_USAGE_UNIFORM,\n mappedAtCreation: false,\n }),\n );\n if (input.cookieMatrixData !== undefined && input.cookieMatrices > 0) {\n requireResource(device.queue.writeBuffer(created, 0, input.cookieMatrixData));\n uploadCount += 1;\n }\n cookieMatrixBuffer = created;\n return created;\n },\n cleanup: (value) => {\n const destroyed = device.destroyBuffer(value);\n if (!destroyed.ok) throw destroyed.error;\n },\n });\n transaction.add({\n // Samplers are bindable GPU resources, not host listeners. Keeping the\n // lifecycle kind aligned with the resource's actual renderer role makes\n // scope inspection and rollback receipts truthful.\n kind: 'binding',\n create: () => {\n const created = requireResource(\n device.createSampler({\n label: 'extended-lighting-clamp-linear',\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n addressModeW: 'clamp-to-edge',\n magFilter: 'linear',\n minFilter: 'linear',\n mipmapFilter: 'nearest',\n }),\n );\n sampler = created;\n return created;\n },\n cleanup: () => undefined,\n });\n const committed = await transaction.commit();\n if (!committed.ok)\n return failure(committed.error.primary.expected, committed.error.primary.message);\n if (\n iesTexture === undefined ||\n cookieTexture === undefined ||\n cookieMatrixBuffer === undefined ||\n sampler === undefined\n ) {\n return failure(\n 'complete extendedLighting candidate resources',\n 'resource transaction returned an incomplete set',\n );\n }\n return ok({\n topology: EXTENDED_LIGHTING_TOPOLOGY,\n generation: scope.generation,\n scope,\n iesSliceCount: input.iesSliceCount,\n cookieSliceCount: input.cookieSliceCount,\n cookieMatrices: input.cookieMatrices,\n sampler,\n iesTexture,\n cookieTexture,\n cookieMatrixBuffer,\n descriptorBytes:\n IES_SLICE_WIDTH * IES_SLICE_HEIGHT * 2 * IES_SLICE_CAPACITY +\n COOKIE_SLICE_SIZE * COOKIE_SLICE_SIZE * 4 * COOKIE_SLICE_CAPACITY +\n COOKIE_MATRIX_BYTES,\n uploadCount,\n });\n}\n\nexport function inspectExtendedLightingResources(\n scope: DeviceScope,\n): ExtendedLightingResourceInspection {\n return {\n topology: EXTENDED_LIGHTING_TOPOLOGY,\n generation: scope.generation,\n status: 'empty',\n accepted: false,\n resourceCount: 0,\n descriptorBytes: 0,\n uploadCount: 0,\n blendInvalidations: 0,\n passCount: 0,\n };\n}\n","// @forgeax/engine-runtime - RenderSystem record stage: frame-snapshot.\n// Extracted from render-system-record.ts (feat-20260704 M3/w17, pure move).\n\nimport type { World } from '@forgeax/engine-ecs';\nimport type { RenderReadVersion } from '@forgeax/engine-ecs/projection';\nimport { vec3 } from '@forgeax/engine-math';\nimport type {\n CompiledRenderGraphInfo,\n ResolvedColorTargetDescriptor,\n} from '@forgeax/engine-render-graph';\nimport type {\n BindGroup,\n BindGroupLayout,\n Buffer,\n RhiDevice,\n Texture,\n TextureView,\n} from '@forgeax/engine-rhi';\nimport type { ClusterBinScratch } from '../cluster-binner';\nimport type { DirectionalShadowQuality } from '../components/directional-shadow-filter';\nimport type { EnvironmentGeneration } from '../environment/generation';\nimport type { EnvironmentLifecycle } from '../environment/lifecycle';\nimport type { DepthOfFieldParams } from '../features/depth-of-field/depth-of-field-params';\nimport type { GpuBuffer } from '../gpu-resource';\nimport type { InstanceCollectionStore } from '../instances';\nimport type { IblBindingInspection } from '../mesh-material-bindings';\nimport type { StandardLightingInspection } from '../pipeline/standard-lighting/inspection';\nimport type { AutoExposureGpuResources } from '../pipeline/standard-output/auto-exposure/gpu';\nimport type { AutoExposureState } from '../pipeline/standard-output/auto-exposure/state';\nimport type { StandardLutGpuResources } from '../pipeline/standard-output/lut-gpu';\nimport type { StandardLutCandidate, StandardLutState } from '../pipeline/standard-output/lut-state';\nimport type { PointShadowInspection } from '../point-shadow-inspection';\nimport type { SsrSpatialAdmission } from '../ssr/admission';\nimport type { SsrHistoryCandidate, SsrHistoryOwner } from '../ssr/history';\nimport type { TemporalGpuState } from '../temporal/gpu';\nimport type { TemporalView } from '../temporal/view';\n\nexport type TemporalCommitOutcome =\n | { readonly kind: 'none' }\n | { readonly kind: 'off'; readonly view: TemporalView }\n | { readonly kind: 'taa'; readonly view: TemporalView };\n\n/** CPU transaction metadata staged beside the renderer-owned GPU candidate. */\nexport interface PendingAutoExposureState {\n readonly state: AutoExposureState;\n readonly generation: number;\n readonly deviceEpoch: number;\n readonly frameId: number;\n}\n\n/** CPU POD staged beside the renderer-owned LUT resources until submit. */\nexport interface PendingStandardLutState {\n readonly state: StandardLutState;\n readonly candidate?: StandardLutCandidate;\n readonly remove: boolean;\n readonly targetGeneration: number;\n readonly deviceEpoch: number;\n}\n\n/**\n * feat-20260708-composited-multi-world-rendering M1 / D-1 / D-9:\n * worldId-entityKey composite key helper. Formula: `worldId * 2^32 + entityKey`.\n *\n * worldId is the index into `worlds[]` (the `draw` call argument). entityKey\n * is the packed Entity u32 (encodeEntity(indexSlot, generation)) surfaced\n * through `RenderableSnapshot.entityKey`.\n *\n * Key properties:\n * - worldId=0 identity: `worldEntityKey(0, k) === k` — single-world path\n * cache behavior is bit-for-bit unchanged (AC-03 regression guarantee).\n * - JS safe integer: worldId < 2^21 keeps the composite key below\n * Number.MAX_SAFE_INTEGER (2^53).\n * - SSOT: all cache-key compositing consumers import this single helper;\n * no inline `worldId * 2^32 + k` duplication (D-9).\n *\n * @internal — exported for unit test + glyph/tilemap/record consumers;\n * not part of the public @forgeax/engine-runtime API surface.\n */\nexport function worldEntityKey(worldId: number, entityKey: number): number {\n return worldId * 4294967296 + entityKey; // 2^32 = 4294967296\n}\n\n/**\n * Cache identity for a renderer-owned instance collection.\n *\n * A collection can be rebound from one entity to another while retaining the\n * same count, revision, and extraction archetype. The collection id is the\n * owner identity in that case; the entity cache key is only the compatibility\n * fallback for legacy snapshots that predate the collection field.\n */\nexport function instanceCollectionCacheKey(\n worldId: number,\n instance: { readonly cacheKey: number; readonly collectionId?: number },\n): number {\n // Keep collection entries in a disjoint numeric namespace from the shared\n // legacy sprite/fold cache. Fold keys occupy -1..-(2^32), while ordinary\n // world/entity keys are non-negative; this range starts below both.\n return -(0x1_0000_0000 + worldEntityKey(worldId, instance.collectionId ?? instance.cacheKey));\n}\n\n/**\n * Cross-frame cache entry for a material bind group whose source material and\n * all resolved GPU resources are stable. The material snapshot identity is\n * the extract-layer invalidation token; the builder only stores entries after\n * all explicit resource handles resolved to resident GPU objects.\n */\nexport interface MaterialBgAssemblyCacheEntry {\n readonly material: MaterialSnapshot;\n /** Invalidates when a texture/sampler residency identity changes. */\n readonly materialResourceEpoch: number;\n readonly materialBgl: BindGroupLayout;\n /** Buffer identity changes when the shared material capacity grows. */\n readonly materialBuffer: Buffer;\n readonly sceneMaterialBuffer?: Buffer;\n readonly skylightResources: SkylightBindGroupResources;\n readonly bindGroup: BindGroup;\n}\n\nimport type { CompiledRenderGraph } from '@forgeax/engine-render-graph';\nimport type { MaterialRenderState, RenderPipelineAsset } from '@forgeax/engine-types';\nimport type { MeshGpuHandles } from '../device/gpu-residency';\nimport type { SkylightBindGroupResources } from '../ibl/skylight-bind-group';\nimport type { InstanceBufferCacheEntry } from '../instance-buffer-cache';\nimport type { CameraSnapshot, VolumetricFogFrameContext } from '../render-contract';\nimport type { RenderPipeline as RenderPipelineDef, RenderPipelineFrame } from '../render-pipeline';\nimport type {\n DispatchEntry,\n MaterialSnapshot,\n PointShadowSnapshot,\n RenderableSnapshot,\n SpotLightSnapshot,\n} from '../render-system-extract';\nimport type { ProbeBlendRecord } from '../scene/probe-blend-record';\nimport type { ShadowAtlas } from '../shadow-atlas';\nimport type {\n TemporalFrame,\n TemporalFrameInput,\n TemporalFrameTransaction,\n} from '../temporal/frame';\nimport type { VolumetricFogInspection } from '../volume/inspection';\nimport type { VolumeTemporalSignature } from '../volume/temporal';\n\n/** Retained probe record bytes carried with one extracted render frame. */\nexport interface ProbeBlendFrameSnapshot {\n readonly records: readonly ProbeBlendRecord[];\n readonly recordByteLength: 160;\n}\n\n/** Renderer-owned GPU cache entry for one object's 160B probe record. */\nexport interface ProbeBlendBufferCacheEntry {\n readonly generation: number;\n readonly bytes: Uint8Array;\n}\n\n/**\n * feat-20260608-create-app-param-surface-trim / M1 / D-8 (q8 user lock):\n * fallback clear color when the world carries no Camera entity. Opaque\n * black `[0, 0, 0, 1]`, replacing the historical\n * `[0.06, 0.06, 0.08, 1.0]` dark-slate sentinel. Single SSOT consumed by\n * the synthetic CameraSnapshot built when `cameras.length === 0`\n * (Case B in `recordFrame`) and read directly by tests\n * (`zero-camera-clear-fallback.test.ts`). AC-05.\n */\nexport const ZERO_CAMERA_CLEAR_FALLBACK: readonly [number, number, number, number] = [0, 0, 0, 1];\n\nexport interface FrameObservationSource {\n readonly texture: Texture;\n readonly descriptor: ResolvedColorTargetDescriptor;\n readonly frameId: number;\n readonly pipelineId: 'forgeax::standard';\n readonly backendId: string;\n}\n\n/** Internal test/diagnostic view of one compiled graph color target. */\nexport interface CurrentGraphTarget {\n readonly name: string;\n readonly texture: Texture;\n /** Stable opaque identity for this RHI handle during the renderer lifetime. */\n readonly textureIdentity: number;\n readonly descriptor: ResolvedColorTargetDescriptor;\n readonly frameId: number;\n /** Monotonic identity of the compiled graph that owns this texture. */\n readonly graphGeneration: number;\n}\n\nconst textureIdentities = new WeakMap<object, number>();\nlet nextTextureIdentity = 1;\n\nconst opaqueResourceIdentities = new WeakMap<object, number>();\nlet nextOpaqueResourceIdentity = 1;\n\n/** Stable detached identity for a renderer-owned opaque resource handle. */\nexport function getOpaqueResourceIdentity(resource: object): number {\n const existing = opaqueResourceIdentities.get(resource);\n if (existing !== undefined) return existing;\n const identity = nextOpaqueResourceIdentity++;\n opaqueResourceIdentities.set(resource, identity);\n return identity;\n}\n\n/**\n * Project an opaque RHI texture handle to a stable diagnostic identity.\n * RHI handles intentionally expose no serializable fields; object identity is\n * the only valid comparison boundary for a copy-time capture.\n */\nexport function getTextureIdentity(texture: Texture): number {\n const object = texture as object;\n const existing = textureIdentities.get(object);\n if (existing !== undefined) return existing;\n const identity = nextTextureIdentity++;\n textureIdentities.set(object, identity);\n return identity;\n}\n\nexport type GraphTargetCaptureReadbackValidation =\n | { readonly ok: true }\n | {\n readonly ok: false;\n readonly code:\n | 'capture-readback-length'\n | 'capture-readback-untouched-sentinel'\n | 'capture-readback-empty'\n | 'capture-readback-non-finite';\n };\n\n/** Validate a mapped rgba16float capture before a consumer decodes its values. */\nexport function validateGraphTargetCaptureReadback(input: {\n readonly bytes: Uint8Array;\n readonly expectedByteLength: number;\n readonly sentinel?: Uint8Array;\n readonly allowZero?: boolean;\n}): GraphTargetCaptureReadbackValidation {\n const { bytes, expectedByteLength, sentinel, allowZero = false } = input;\n if (bytes.byteLength !== expectedByteLength)\n return { ok: false, code: 'capture-readback-length' };\n if (sentinel?.every((value, index) => bytes[index] === value)) {\n return { ok: false, code: 'capture-readback-untouched-sentinel' };\n }\n if (!allowZero && bytes.every((value) => value === 0)) {\n return { ok: false, code: 'capture-readback-empty' };\n }\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n let index = 0;\n // Inspect both half-float exponents per word. DataView also preserves\n // little-endian capture semantics for unaligned slices and host byte orders.\n for (; index + 3 < bytes.byteLength; index += 4) {\n const word = view.getUint32(index, true);\n if ((word & 0x7c00) === 0x7c00 || (word & 0x7c000000) === 0x7c000000)\n return { ok: false, code: 'capture-readback-non-finite' };\n }\n if (index + 1 < bytes.byteLength && (view.getUint16(index, true) & 0x7c00) === 0x7c00)\n return { ok: false, code: 'capture-readback-non-finite' };\n return { ok: true };\n}\n\n/**\n * Receipt delivered after a selected pass-replay raster pass has encoded.\n * The depth view and target handles are the frame-resolved objects used by\n * the graph; the numeric texture identity is derived by getTextureIdentity.\n */\nexport interface GraphTargetPassReplayReceipt {\n readonly passName: string;\n readonly executionIndex: number;\n readonly resolvedDepthStencilAttachmentView: TextureView;\n readonly graphGeneration: number;\n readonly targetName: string;\n readonly targetView: TextureView;\n readonly targetTexture: Texture;\n readonly targetTextureIdentity: number;\n}\n\nexport type GraphTargetPassReplayCallback = (receipt: GraphTargetPassReplayReceipt) => void;\n\n/** Receipt delivered once after a complete selected prefix reaches its boundary pass. */\nexport interface GraphTargetPassReplayPrefixReceipt extends GraphTargetPassReplayReceipt {\n /** The compiled-order prefix that was replayed. */\n readonly replayPassNames: readonly string[];\n /** The unique depth-bearing raster pass used as the observation anchor. */\n readonly depthAttachmentPassName: string;\n /** The final pass in the selected prefix. */\n readonly observeAfterPassName: string;\n readonly depthAttachmentExecutionIndex: number;\n}\n\nexport type GraphTargetPassReplayPrefixCallback = (\n receipt: GraphTargetPassReplayPrefixReceipt,\n) => void;\n\n/** Internal readback request consumed by the record encoder in the same submit. */\nexport type GraphTargetCaptureRequest =\n | {\n /** The default preserves the original target-copy request shape. */\n readonly kind?: 'target-copy';\n readonly name: string;\n /** Optional one-shot pass selection for internal graph-target diagnostics. */\n readonly replayPassNames?: readonly string[];\n readonly buffer: Buffer;\n readonly bytesPerRow: number;\n readonly width: number;\n readonly height: number;\n /** Descriptor contract checked against the resolved target at copy time. */\n readonly expected: {\n readonly format: ResolvedColorTargetDescriptor['format'];\n readonly width: number;\n readonly height: number;\n readonly usage: number;\n /** Optional caller binding; when present it is checked at copy time. */\n readonly identity?: {\n readonly graphGeneration: number;\n readonly frameId: number;\n readonly textureIdentity: number;\n };\n };\n }\n | {\n /** Execute selected compiled passes without requesting a target copy. */\n readonly kind: 'pass-replay';\n readonly replayPassNames: readonly string[];\n /** Optional graph target used to validate the selected pass attachment. */\n readonly targetName?: string;\n /** Optional callback invoked after each selected pass encodes. */\n readonly onPassEncoded?: GraphTargetPassReplayCallback;\n /** Optional one-shot callback invoked after the selected prefix boundary encodes. */\n readonly depthAttachmentPassName?: string;\n readonly observeAfterPassName?: string;\n readonly onPrefixEncoded?: GraphTargetPassReplayPrefixCallback;\n };\n\n/** Renderer-private readback request for the Standard fallback MRT. */\nexport interface ReflectionFallbackReadbackRequest {\n readonly name: string;\n readonly buffer: Buffer;\n readonly bytesPerRow: number;\n readonly width: number;\n readonly height: number;\n readonly expected: {\n readonly format: ResolvedColorTargetDescriptor['format'];\n readonly width: number;\n readonly height: number;\n readonly usage: number;\n readonly graphGeneration: number;\n readonly frameId: number;\n readonly textureIdentity: number;\n };\n encoded: boolean;\n}\n/**\n * Build a synthetic CameraSnapshot the record stage uses when the world\n * carries no Camera entity. Identity-shaped projection / view inputs\n * keep the existing matrix math numerically stable; clear-color quartet\n * sourced from `ZERO_CAMERA_CLEAR_FALLBACK` so the swap-chain still\n * paints `[0, 0, 0, 1]` (AI-user friendly observable signal that the\n * `'render-system-no-camera'` diagnostic fired without leaving stale\n * pixels on screen).\n */\nexport function makeZeroCameraFallbackSnapshot(): CameraSnapshot {\n // Identity world mat4 so `mat4.invert(world)` yields identity view.\n const identityWorld = new Float32Array(16);\n identityWorld[0] = 1;\n identityWorld[5] = 1;\n identityWorld[10] = 1;\n identityWorld[15] = 1;\n return {\n position: vec3.create(0, 0, 0),\n world: identityWorld,\n fov: Math.PI / 4,\n aspect: 1,\n near: 0.1,\n far: 100,\n // feat-20260613 M6 / w20: synthetic camera defaults to perspective so\n // the CSM extract path stays consistent with the previously-implicit\n // perspective shape (unchanged behavior; explicit field).\n projection: 'perspective',\n orthoLeft: -1,\n orthoRight: 1,\n orthoBottom: -1,\n orthoTop: 1,\n tonemap: 'none',\n exposure: 1.0,\n whitePoint: 4.0,\n antialias: 'none',\n bloom: 'off',\n bloomThreshold: 1.0,\n bloomIntensity: 1.0,\n bloomBlurRadius: 4.0,\n clearColor: ZERO_CAMERA_CLEAR_FALLBACK,\n };\n}\n\n/**\n * Per-RenderSystem mutable frame state.\n *\n * Owned by the `createRenderSystem` closure; advanced once per\n * `recordFrame` invocation. The `instanceBuffers` map holds the per-entity\n * GPU storage buffers for Instances-bearing entities (cache key = the\n * renderer-owned collection id, with the packed Entity u32 retained only for\n * legacy snapshots); entries are recreated when the `archVersion` bumps or\n * `byteLength` changes.\n *\n * feat-20260518-pbr-direct-lighting-mvp M3 / w14 (AC-17 a): the\n * `warnedZeroLightStandard` flag latches the first-frame warning that\n * fires when the world contains a StandardMaterial entity but zero\n * DirectionalLight entries — once latched the next 100 frames suppress\n * the warning so the AI user is not flooded with repeated noise (charter\n * P3 silent failure -> explicit warning at most once per RenderSystem\n * lifetime).\n */\nexport interface RenderFrameState {\n frameNumber: number;\n /** Final-submit Standard IBL binding-chain receipt for this frame. */\n iblBindingInspection?: IblBindingInspection;\n /** Demand for the frame-local Standard fallback MRT. */\n reflectionFallbackDemand?: boolean;\n /** Whether the active camera explicitly requested SSR this frame. */\n ssrRequested?: boolean | undefined;\n /** Current renderer-owned SSR spatial admission projection. */\n ssrSpatialAdmission?: SsrSpatialAdmission | undefined;\n /** Persistent SSR history owner; candidate is promoted only after submit. */\n ssrHistoryOwner?: SsrHistoryOwner | undefined;\n ssrHistoryCandidate?: SsrHistoryCandidate | undefined;\n /** Reused CPU parameter payload for the SSR temporal resolve. */\n ssrTemporalParamsPayload?: Uint8Array | undefined;\n /** Last camera identity used by the SSR history reset seam. */\n ssrLastCameraEntity?: number | undefined;\n ssrLastHistoryVersion?: number | undefined;\n /** Monotonic compiled-graph identity used by diagnostic readbacks. */\n graphGeneration: number;\n /** Number of successfully submitted TAA frames; failed attempts do not advance it. */\n successfulTemporalFrameIndex?: number;\n /** The renderer-owned accepted-submit temporal fact consumed by consumers. */\n temporalFrame?: TemporalFrame | undefined;\n /** The sole transaction that advances temporal history after queue.submit. */\n readonly temporalFrameTransaction: TemporalFrameTransaction;\n /** Staged input is consumed only by the graph submit owner. */\n temporalFrameInput: TemporalFrameInput | undefined;\n /** Optional graph resource lookup used by low-level record helpers and tests. */\n perFrameGraph?: {\n readonly getColorTargetDescriptor: (key: string) => ResolvedColorTargetDescriptor | undefined;\n readonly getColorTargetView: (key: string) => TextureView | undefined;\n readonly getColorTargetTexture: (key: string) => Texture | undefined;\n readonly graphGeneration: number;\n } | null;\n graphTargetCapture?: GraphTargetCaptureRequest | undefined;\n /** One-frame producer-owned copy target for fallback MRT readback. */\n reflectionFallbackReadback?: ReflectionFallbackReadbackRequest | undefined;\n /** Last successfully rendered static directional shadow atlas token. */\n directionalShadowCache: DirectionalShadowCache | null;\n /** Last successfully submitted camera post-process mode. */\n lastSuccessfulBloom: 'off' | 'on';\n /** Bloom record receipts staged by this frame; cleared on abort. */\n bloomFrameReceipts?: BloomFrameReceipts | undefined;\n /** Set by a directional shadow pass when this frame refreshed the atlas. */\n directionalShadowCacheRecorded: boolean;\n /** The sole compiled owner for compute, copy, feature, and raster work. */\n compiledFrameGraph: CompiledRenderGraph<RenderPipelineFrame> | null;\n compiledFrameGraphTopologyKey: string | null;\n /** Monotonic generation of successfully promoted compiled graphs. */\n compiledFrameGraphGeneration: number;\n /**\n * DoF graph candidate staged until the surrounding frame transaction\n * submits. The previous graph, access projection, generation, and lighting\n * signature are restored together when encoding or submission aborts.\n */\n depthOfFieldPreviousGraph: CompiledRenderGraph<RenderPipelineFrame> | null;\n depthOfFieldPreviousGraphKey: string | null;\n depthOfFieldPreviousPerFrameGraph?: RenderFrameState['perFrameGraph'];\n depthOfFieldPreviousGraphGeneration: number;\n depthOfFieldPreviousStandardLightingGraphSignature: string;\n depthOfFieldCandidateGraph: CompiledRenderGraph<RenderPipelineFrame> | null;\n /** DoF graph/params detached at the same successful-submit boundary. */\n depthOfFieldAccepted?:\n | {\n readonly params: DepthOfFieldParams;\n readonly graph: CompiledRenderGraphInfo;\n readonly deviceGeneration: number;\n }\n | undefined;\n /** A DoF candidate was present when the frame failed to submit. */\n depthOfFieldLastSubmitFailed?: boolean | undefined;\n /**\n * Last-known-good graph held while a volume topology candidate is tested.\n * The candidate is promoted only after its command buffer is submitted;\n * failed encoding/finish/submit restores this graph and its topology key.\n */\n volumetricFogPreviousGraph: CompiledRenderGraph<RenderPipelineFrame> | null;\n volumetricFogPreviousGraphKey: string | null;\n volumetricFogCandidateGraph: CompiledRenderGraph<RenderPipelineFrame> | null;\n /** Two renderer-owned parameter slots; only the pending slot is writable. */\n volumetricFogParamsBuffers: [Buffer | null, Buffer | null];\n /** Candidate parameter slot, promoted only after queue submission succeeds. */\n volumetricFogParamsPendingSlot: 0 | 1 | null;\n /** Parameter slot consumed by the last accepted volume frame. */\n volumetricFogParamsAcceptedSlot: 0 | 1 | null;\n /** CPU copy of the accepted parameter payload for degraded-frame staging. */\n volumetricFogAcceptedParams: Float32Array | undefined;\n /** CPU copy of the current candidate payload before submit. */\n volumetricFogPendingParams: Float32Array | undefined;\n /** Last candidate/accepted volume projection exposed through inspect(). */\n volumetricFogInspection: VolumetricFogInspection;\n /** Accepted volume POD/context retained while a later candidate degrades. */\n volumetricFogAccepted: import('../render-system-extract').ExtractedVolumetricFog | undefined;\n volumetricFogAcceptedContext: VolumetricFogFrameContext | undefined;\n /** Accepted graph identity and ping-pong slot for temporal volume history. */\n volumetricFogHistoryGraph: CompiledRenderGraph<RenderPipelineFrame> | null;\n volumetricFogHistorySlot: 0 | 1 | null;\n volumetricFogHistorySignature: VolumeTemporalSignature | null;\n readonly retiredCompiledFrameGraphs: Set<CompiledRenderGraph<RenderPipelineFrame>>;\n /** Physical outputs projected by typed graph passes for downstream observers. */\n currentFrameObservationSource: FrameObservationSource | undefined;\n /** Completed-frame source for the producer-owned fallback MRT. */\n reflectionFallbackObservationSource?: FrameObservationSource | undefined;\n /** Completion fence for the producer-owned fallback row/readback promotion. */\n reflectionFallbackCompletion?: Promise<void> | undefined;\n /** Camera antialias mode for the last successfully submitted graph. */\n lastSuccessfulCameraAntialias: CameraSnapshot['antialias'] | undefined;\n /** Staged TAA GPU state is promoted only after queue.submit succeeds. */\n temporalGpuState: TemporalGpuState | undefined;\n /** Device-scoped auto-exposure buffers imported by the Standard graph. */\n autoExposureGpuResources?: AutoExposureGpuResources | undefined;\n /** Candidate auto-exposure buffers; promoted only after queue.submit succeeds. */\n pendingAutoExposureGpuResources?: AutoExposureGpuResources | undefined;\n /** Accepted auto-exposure inspection state; promoted only after submit. */\n autoExposureState?: AutoExposureState | undefined;\n /** Candidate auto-exposure inspection state; cleared on any failed frame. */\n pendingAutoExposureState?: PendingAutoExposureState | undefined;\n /** Prepared ordinary TextureAsset LUT candidate for the Standard graph. */\n standardLutGpuResources?: StandardLutGpuResources | undefined;\n /** Candidate LUT resources; promoted only after queue.submit succeeds. */\n pendingStandardLutGpuResources?: StandardLutGpuResources | undefined;\n /** Accepted LUT inspection state; promoted only after submit. */\n standardLutState: StandardLutState;\n /** Candidate LUT inspection state; cleared on any failed frame. */\n pendingStandardLutState?: PendingStandardLutState | undefined;\n /** Last successful TAA GPU state; candidate replacement stays staged until submit. */\n activeTemporalGpuState: TemporalGpuState | undefined;\n /** Submitted temporal generations retained until their queue fence resolves. */\n readonly retiringTemporalGpuStates: Set<TemporalGpuState>;\n /** Last successful projection; candidate frames never overwrite it. */\n lastSuccessfulTemporalView: TemporalView | undefined;\n pendingTemporalCommit: TemporalCommitOutcome;\n /** Staged environment generation is promoted only after queue.submit succeeds. */\n environmentGeneration: EnvironmentGeneration | undefined;\n environmentFrame?: import('../environment/frame').SelectedEnvironmentFrame | undefined;\n pendingAtmospherePublish?: (() => void) | undefined;\n readonly environmentLifecycle: EnvironmentLifecycle | undefined;\n currentDirectionalShadowView: TextureView | null;\n currentSpotShadowView: TextureView | null;\n readonly instanceBuffers: Map<number, InstanceBufferCacheEntry>;\n /** Renderer-owned collection owner used for record-stage residency facts. */\n readonly instanceCollections?: InstanceCollectionStore;\n /** Stable buffers for renderer-owned collections split by device cap. */\n readonly instanceBufferChunks?: Map<string, InstanceBufferCacheEntry>;\n /** Per-object ProbeBlendRecord buffers; upload is one atomic 160B write. */\n readonly probeBlendBuffers: Map<number, ProbeBlendBufferCacheEntry>;\n /** One renderer-owned record array; each object selects its 256B-aligned lane. */\n probeBlendRecordBuffer?: GpuBuffer;\n probeBlendRecordBufferCapacity: number;\n /** Per-entity vertex buffers for the Standard CPU morph lane. */\n readonly morphBuffers?: Map<number, MorphBufferCacheEntry>;\n readonly hdrpClusterBinScratch: ClusterBinScratch;\n /** Reusable HDRP cluster output buffers; sized once and grown only if the grid/cap changes. */\n hdrpClusterGridScratch: Uint32Array | null;\n hdrpLightIndexListScratch: Uint32Array | null;\n /** Device-owned membership binding; layout and device must match the active pipeline. */\n hdrpClusterMembership: {\n readonly device: RhiDevice;\n readonly layout: BindGroupLayout;\n readonly bindGroup: BindGroup;\n /** Cluster buffer identity keeps this group aligned with grown bundles. */\n readonly clusterGridBuffer: Buffer;\n } | null;\n /**\n * Signature of the Standard lighting declaration accepted by the compiled\n * graph. Payload uploads and membership bindings must match this signature;\n * a failed candidate never changes it.\n */\n standardLightingGraphSignature: string;\n /** Last prepared Standard transport facts projected for Renderer.inspect(). */\n standardLightingInspection?: StandardLightingInspection | undefined;\n /** Last submitted point-shadow atlas budget projection. */\n pointShadowInspection?: PointShadowInspection | undefined;\n transientInstanceBuffers: InstanceBufferCacheEntry[];\n warnedZeroLightStandard: boolean;\n /**\n * feat-20260608-multi-light-warn-once M3: once-warn latch for the\n * single-directional authoring constraint. Standard local lights use the\n * unified Cluster budget; there is no per-kind local-light cap.\n */\n warnedMultiLightDirectional: boolean;\n /**\n * feat-20260630-equirect-kind-internalized-ibl-declarative-skyligh M3 / w19:\n * once-warn latches for >1 Skylight / >1 SkyboxBackground entity. Fire at most\n * once per RenderSystem lifetime so the multi-entity warn (which names the\n * winning entity handle, F-8) does not flood the console every frame.\n */\n warnedMultiSkylight: boolean;\n warnedMultiSkybox: boolean;\n /** feat-20260531-skybox-env-background M3 / w20: once-warn when camera\n * tonemap is 'none' but a SkyboxBackground entity exists. Skybox needs\n * the HDR render target allocated by the tonemap path; without it the\n * skybox pass is skipped (plan-strategy D-2 NOTE). */\n warnedSkyboxTonemapNone: boolean;\n /**\n * Per-handle warn-once anchor for the missing baseColor-texture fallback,\n * shared by every textured material path (sprite / sprite-lit / standard-pbr\n * / pbr-skin / unlit — feat-20260520-2d-sprite-layer-mvp M-3 / w25 seeded it\n * for sprites; feat-future-pbr-missing-texture-fallback-explicit generalised\n * it to PBR/skin so GLB textures that fail to reach the GPU no longer render\n * silently flat). A `Set<number>` keyed by the raw Handle<TextureAsset> id -\n * the writer fires `console.warn` exactly once per missing texture handle per\n * RenderSystem lifetime so AI users see a single actionable message without\n * per-frame log flooding. The set lives across frames so the second frame on\n * the same missing handle stays silent (charter P3 explicit failure:\n * warn-once preserves signal / noise floor while structured RhiError below\n * stays per-frame fire).\n *\n * Note on the WeakSet/Set choice: plan-strategy mentions WeakSet but\n * Handle values are numeric brand u32s (not object references), so\n * WeakSet<object> is not applicable; Set<number> gives identical\n * warn-once-per-handle semantics at zero additional cost (charter F1\n * minimal surface; the per-RenderSystem lifetime cap is the upper\n * bound).\n */\n readonly warnedMissingBaseColorTextureHandles: Set<number>;\n /**\n * feat-20260527-sprite-nineslice M2 / w11 + M4 / w16 (AC-16): once-per-\n * renderable guard for the `nineslice.scale-too-small` metric increment.\n * Keyed by `renderableIndex` so the second frame on the same mis-scaled\n * entity does NOT keep bumping the counter — AI users see one counter\n * tick per offending entity per RenderSystem lifetime, matching the\n * single-event semantics of the structured fail-fast (charter P3:\n * machine-readable signal, not a per-frame inflation). M4 retired the\n * placeholder console.warn; the increment lands on the per-Renderer\n * EngineMetrics through `runtime.metrics.increment(...)`.\n */\n readonly warnedNineSliceScaleEntities: Set<number>;\n /**\n * feat-20260630-equirect-kind-internalized-ibl-declarative-skyligh M3 / w18:\n * per-handle fire-once anchor for the lazy equirect-to-cubemap projection\n * failure. A `Set<number>` keyed by the raw Handle<EquirectAsset> id - the\n * record arm fires the structured `EquirectProjectionFailedError` exactly\n * once per failed source per RenderSystem lifetime (the store records\n * `status:'failed'` permanently and never retries, R-2 / AC-09; without this\n * latch the record arm would re-fire the error every frame). The set lives\n * across frames so the second frame on the same failed handle stays silent\n * (charter P3: warn-once preserves signal / noise floor).\n */\n readonly firedEquirectProjectionFailedHandles: Set<number>;\n /**\n * feat-20260622-handle-to-id-allocator-elimination M1 / w3: per-frame\n * bind group caches converted to nested WeakMap chain roots (D-3).\n * Each root is a WeakMap<object, WeakMap<...>> walked by\n * getOrCreateFromChain; the chain depth varies by variant\n * (view-main = 7, mesh = 1, hdrp-unified = 5, skin = 2).\n * Roots are stable between device recoveries and replaced when the renderer\n * swaps to a fresh device. Chain keys are always inner buffer handles, never\n * wrappers (D-3).\n */\n viewBindGroupCache: WeakMap<object, unknown>;\n meshBindGroupCache: WeakMap<object, unknown>;\n /**\n * feat-20260622-handle-to-id-allocator-elimination M1 / w2: per-entity\n * bind group caches scoped by entityKey (packed u32 as number).\n * Outer Map<number, WeakMap<handle, ...>> lets GC collect entries for\n * destroyed entities whose handles are unreachable; per-entity material\n * and instances share the same two-level shape (D-1). The inner WeakMap\n * value is opaque (`unknown`) because `getOrCreateFromChain` walks a\n * variable-depth chain — intermediate handles map to nested WeakMaps and\n * only the final handle maps to the variant->BindGroup leaf Map. Direct\n * readers (HDRP shadow-instances read end) assert the leaf shape locally.\n */\n /**\n * feat-20260708-composited-multi-world-rendering M1 / D-1a #2: outer Map\n * keyed by `worldEntityKey(worldId, entityKey)`. Inner WeakMap unchanged.\n */\n readonly materialBgPerEntity: Map<number, WeakMap<object, unknown>>;\n /**\n * feat-20260708-composited-multi-world-rendering M1 / D-1a #3: outer Map\n * keyed by `worldEntityKey(worldId, entityKey)`. Inner WeakMap unchanged.\n */\n readonly instancesBgPerEntity: Map<number, WeakMap<object, unknown>>;\n /** Identity-keyed instances BGs shared across entities using the same buffer. */\n readonly instancesBgShared: WeakMap<object, unknown>;\n /**\n * feat-20260622-handle-to-id-allocator-elimination M1 / w2: cross-entity\n * shared material bind group cache (OQ-1 option A). Outer key is the\n * material shaderId string; inner chain is a WeakMap keyed by the same\n * handle objects used in per-entity chains. Reuses the generic\n * `getOrCreatePerEntity` helper with outerKey string|number (D-1).\n */\n readonly materialBgShared: Map<string, WeakMap<object, unknown>>;\n /** Cross-frame fast path for fully-resident, immutable material snapshots. */\n readonly materialBgAssemblyCache: Map<string, MaterialBgAssemblyCacheEntry>;\n /** Opaque shadow fallback bindings follow physical resources across scene replacement. */\n shadowMaterialBindGroups: WeakMap<object, unknown>;\n /**\n * Post-process bind group cache: nested WeakMap chain root shared by the\n * built-in bloom (bright / blur-H / blur-V / composite), FXAA, and HDRP SSAO\n * (calc / blur) fullscreen passes. Each of these passes samples graph-owned\n * transient render targets (hdrColor / ldrColor / bloom* / ssaoRaw /\n * gbuf0 / hdrDepth); on canvas resize the graph retires the old physical\n * textures and allocates new ones, so the bind group must be rebuilt to\n * reference the new TextureView identity. Keying the cache on the physical\n * TextureView (or `::tex` texture handle for passes that recreate their bound\n * view every frame) makes invalidation automatic: a resized target yields a\n * new key object -> WeakMap miss -> factory rebuild, and dead views are GC'd\n * (same identity-invalidation mechanism as view/mesh caches, D-3). Replaces\n * the pre-fix `pp.*BindGroup === null` single-slot caches that never\n * invalidated on resize and submitted destroyed textures.\n */\n postProcessBgCache: WeakMap<object, unknown>;\n /**\n * Raw handle of the currently installed RenderPipelineAsset (0 = builtin).\n * Installation brands the next candidate topology; the prior compiled graph\n * remains last-known-good until the candidate compiles successfully.\n */\n installedPipelineHandle: number;\n /**\n * Active topology declaration resolved from the pipeline registry.\n */\n activePipeline: RenderPipelineDef;\n /**\n * Install-time config projected into `RenderPipelineTopology.config`.\n */\n installedPipelineConfig: RenderPipelineAsset['config'];\n /**\n * feat-20260608-cluster-lighting M5 / w20 + M6 / w23 + M5 / w22:\n * once-per-frame fire dedup set for Standard per-frame fail-soft errors\n * (`standard-light-budget-exceeded`, `standard-cluster-index-overflow`). Cleared\n * at the end of each frame so the next frame re-fires if the condition\n * persists. Set<string> keyed by RuntimeErrorCode literal.\n */\n standardOncePerFrameFired: Set<string>;\n /**\n * feat-20260612-point-light-shadows-urp-hdrp M3 / T-M3-2 (plan-strategy §D-1).\n * Lazily-allocated cube_array shadow atlas owned by the RenderSystem\n * lifetime. `null` until the first frame whose `lights.pointShadow` is\n * non-empty (zero-shadow scenes never allocate; AC-09). The atlas is\n * disposed by the renderer dispose path; subsequent frames with a non-empty\n * snapshot list re-allocate.\n */\n pointShadowAtlas: ShadowAtlas | null;\n /**\n * feat-20260612-point-light-shadows-urp-hdrp M3 / T-M3-2 (plan-strategy §D-3):\n * per-frame projection of `lights.pointShadow` from the extract stage. The\n * typed point-shadow pass reads this list to drive the 6 x N face iteration.\n * Empty array means the topology declares no point-shadow passes.\n */\n pointShadowSnapshots: readonly PointShadowSnapshot[];\n /**\n * feat-20260622-chunk-gpu-instancing-sprite-tilemap M1 / w4 (D-1):\n * last fold-pass output, computed at `recordFrame` entry from the\n * transparent-sort-ordered dispatch + mode-gate (D-5: only mode 0\n * folds; other modes yield singleton buckets). Currently an\n * observational compute — the drawIndexed swap (1 instanced draw per\n * fold bucket) is the follow-on integration that wires each bucket\n * into the sprite-pass / geometry-pass dispatch loops. The bucket\n * count is the source of truth for `render.instancing.foldedDraws`\n * metric (M3 / w13) — every fold-eligible bucket (bucketSize >= 1\n * under mode 0 AND not bypassed) contributes one increment.\n */\n lastFoldBucketCount: number;\n /**\n * feat-20260625-spot-light-shadow-mapping M2 / w9 (D-2): per-frame projection\n * of `lights.spot` from the extract stage. The typed spot-shadow graph\n * pass reads this list to render each\n * castShadow spot's perspective depth into its `spotShadowDepth` atlas tile\n * (viewport keyed on `shadowAtlasTile`). `recordFrame` writes it before\n * graph execution. Spots with `shadowAtlasTile < 0` (castShadow:false,\n * degenerate direction, or clipped beyond cap 4) are skipped — zero\n * shadow-casting spots means zero spot shadow passes (AC-03).\n */\n spotShadowSnapshots: readonly SpotLightSnapshot[];\n}\n\nexport interface MorphBufferCacheEntry {\n readonly buffer: GpuBuffer;\n readonly byteLength: number;\n}\n\n/**\n * feat-20260518-pbr-direct-lighting-mvp M5 / w22.11 (D-2 + D-10 + AC-06):\n * mutable per-frame dispatch counter object owned by `createRenderSystem`\n * and bumped here at the actual `pass.setPipeline(...)` call site (the\n * only point with both `mat.materialShaderId` and `mesh.layoutProjection` in scope).\n * Unlit / custom shader pipeline dispatch tracked here.\n */\nexport interface DispatchCounts {\n unlit: number;\n /** feat-20260523 M4-T07: 'standard' counter removed; schema-driven\n * materials are tracked via materialShaderId in the pipeline cache. */\n}\n\n/**\n * feat-20260531-per-frame-bind-group-cache M1 / w4: per-frame\n * createBindGroup counter. Closure-mutable object aligned with\n * DispatchCounts precedent. Reset in draw(world) entry, bumped on\n * cache-miss createBindGroup calls (M2-M4).\n */\nexport interface BindGroupCounts {\n createBindGroup: number;\n /**\n * Debug-only: records the variant of every cache-miss BindGroup created via\n * `getOrCreateFromChain` for unit-test observability. Production paths do\n * not read this array.\n */\n keys: string[];\n}\n\n/**\n * Successful Bloom record operations staged for the current frame. These\n * counters are promoted only after the shared renderer queue submission.\n */\nexport interface BloomFrameReceipts {\n readonly uploadCount: number;\n readonly bindGroupCount: number;\n readonly encodeCount: number;\n}\n\n/**\n * A renderable resolved against the AssetRegistry for the current frame:\n * its source snapshot, the GPU mesh handles, the row index used to correlate\n * transparent-sort output back to this entry, and an optional per-material\n * renderState override (bug-20260527-renderstate-pipeline-dispatch-gap D-4).\n * Module-scoped so RenderPipelineContext can type `validated` / `validatedOrdered`\n * without a dynamic type escape (was a recordFrame-local interface before F-4).\n */\nexport interface ValidatedRenderable {\n readonly source: RenderableSnapshot;\n /** World that owns the renderable's asset handles and material snapshots. */\n readonly world?: World;\n readonly mesh: MeshGpuHandles;\n readonly renderableIndex: number;\n readonly renderState: MaterialRenderState | undefined;\n /**\n * Canonical authored material-variant request folded from the selected\n * pass's `defines` map. Capability axes are merged at the renderer seam;\n * this field carries only the pass-owned selection into record.\n */\n readonly variantSet?: string | undefined;\n /**\n * w10: per-pass stencil reference value folded from\n * {@link DispatchEntry.stencilReference} (draw-call dynamic state). The draw\n * loop calls `pass.setStencilReference(stencilReference ?? 0)` before each\n * draw; `undefined` falls back to the WebGPU default 0 (semantic no-op).\n */\n readonly stencilReference: number | undefined;\n}\n\n/**\n * Cross-frame validity token for the directional shadow atlas.\n *\n * The atlas is a render target, not authored state. Keeping its validity\n * token beside the other RenderFrameState caches lets recordFrame skip a\n * static caster submission without teaching the public render-pipeline\n * contract about caching. Every source that can change caster depth is part\n * of the token: world mutation, asset catalogue, graph/target identity, CSM\n * matrices, and the GPU mesh-residency epoch.\n *\n * @internal\n */\nexport interface DirectionalShadowCache {\n readonly worlds: readonly World[];\n readonly worldStateTokens: readonly DirectionalShadowWorldState[];\n readonly assetCatalogEpoch: number;\n readonly pipelineHandle: number;\n readonly graphTopologyKey: string | null;\n readonly shadowMapSize: number;\n readonly cascadeCount: number;\n readonly directionalShadowQuality: DirectionalShadowQuality;\n readonly lightViewProj: readonly Float32Array[];\n readonly meshResidencyEpoch: number;\n}\n\n/**\n * ECS state that can change the contents of a directional shadow map.\n *\n * The ECS-owned RenderReadLease is the only render-facing mutation boundary.\n * Its version is intentionally conservative: any published World change\n * invalidates the cached atlas, while render never reaches through World for\n * component-clock storage.\n */\nexport interface DirectionalShadowWorldState {\n readonly worldIdentity: string;\n readonly version: RenderReadVersion;\n}\n","import type { SceneDataLane, SceneDataSchemaId } from './scene-data';\n\nexport interface SceneDataCoverage {\n readonly schema: SceneDataSchemaId;\n readonly lane: SceneDataLane;\n readonly producerId: string;\n readonly complete: boolean;\n readonly contributorIds: readonly string[];\n readonly exactContributorIds: readonly string[];\n readonly reactiveContributorIds: readonly string[];\n readonly missingContributorIds: readonly string[];\n readonly omittedMissingContributorCount: number;\n}\n\nexport interface TemporalCoverage {\n readonly width: number;\n readonly height: number;\n readonly bytes: number;\n readonly fullScreen: true;\n}\n\nexport function createTemporalCoverage(width: number, height: number): TemporalCoverage {\n if (!Number.isSafeInteger(width) || width <= 0) throw new RangeError('width must be positive.');\n if (!Number.isSafeInteger(height) || height <= 0)\n throw new RangeError('height must be positive.');\n return Object.freeze({ width, height, bytes: 34 * width * height, fullScreen: true as const });\n}\n\nexport type SceneDataContributorKind = 'exact' | 'reactive';\nexport interface SceneDataContributor {\n readonly id: string;\n readonly kind: SceneDataContributorKind;\n}\nexport function classifySceneDataCoverage(input: {\n readonly contributors: readonly SceneDataContributor[];\n readonly requiredContributorIds: readonly string[];\n}): {\n readonly exactContributorIds: readonly string[];\n readonly reactiveContributorIds: readonly string[];\n readonly missingContributorIds: readonly string[];\n readonly omittedMissingContributorCount: number;\n readonly complete: boolean;\n} {\n const exactContributorIds = input.contributors.filter((c) => c.kind === 'exact').map((c) => c.id);\n const reactiveContributorIds = input.contributors\n .filter((c) => c.kind === 'reactive')\n .map((c) => c.id);\n const available = new Set(input.contributors.map((c) => c.id));\n const missing = input.requiredContributorIds.filter((id) => !available.has(id));\n return {\n exactContributorIds: Object.freeze(exactContributorIds),\n reactiveContributorIds: Object.freeze(reactiveContributorIds),\n missingContributorIds: Object.freeze(missing.slice(0, 32)),\n omittedMissingContributorCount: Math.max(0, missing.length - 32),\n complete: missing.length === 0,\n };\n}\nexport function scanSceneDataCoverage(input: {\n readonly schema: SceneDataSchemaId;\n readonly lane: SceneDataLane;\n readonly producerId: string;\n readonly contributorIds: readonly string[];\n readonly requiredContributorIds: readonly string[];\n}): SceneDataCoverage {\n const classification = classifySceneDataCoverage({\n contributors: input.contributorIds.map((id) => ({ id, kind: 'exact' as const })),\n requiredContributorIds: input.requiredContributorIds,\n });\n return Object.freeze({\n schema: input.schema,\n lane: input.lane,\n producerId: input.producerId,\n ...classification,\n contributorIds: Object.freeze([...input.contributorIds]),\n });\n}\n","// @forgeax/engine-runtime - render package shader-stage visibility values.\n//\n// Keep the WebGPU bit values in one dependency-free owner because render\n// package layout builders also run against the null and WebGL2-compatible RHI\n// shims where the browser's GPUShaderStage global is unavailable.\n\nexport const GPU_SHADER_STAGE_VERTEX = 0x1;\nexport const GPU_SHADER_STAGE_FRAGMENT = 0x2;\nexport const GPU_SHADER_STAGE_COMPUTE = 0x4;\n","// pbr-pipeline.ts -- PBR / unlit pipeline-layout factories (M4 round-4 D-5).\n//\n// Anchors:\n// - plan-strategy D-5 (round-4 REVISED): the PBR pipeline keeps a 4-slot\n// pipeline layout `[view, material, mesh-array, instances]`. The\n// material BGL grows from the derived user region by appending the 7\n// Skylight resources via `mergeSkylightIntoMaterialBgl`. The\n// unlit pipeline keeps its 7-entry material BGL (no Skylight binding\n// 7..13 contamination) so unlit demos don't carry IBL state.\n// - charter P4: same pipeline layout shape drives Skylight present +\n// absent paths -- AI users do not branch on Skylight existence.\n// - feat-20260520-skylight-ibl-cubemap M4 / t59 (round-4): the\n// pipeline-layout construction migrates out of `createRenderer.ts`\n// into this dedicated module so M4 round-4 tests can mock the device\n// and inspect the captured descriptors without standing up the full\n// createRenderer + asset registry + manifest stack.\n//\n// The factory functions return both the captured handles AND the\n// `bindGroupLayouts` array passed to `device.createPipelineLayout`. Callers\n// (the createRenderer step that wires the standard + standard-HDR\n// `RenderPipeline` instances) consume the result by name; tests inspect\n// `device.createBindGroupLayout.mock.calls` to verify shape (t57).\n\nimport type {\n BindGroup,\n BindGroupEntry,\n BindGroupLayout,\n Buffer,\n PipelineLayout,\n RhiDevice,\n Sampler,\n TextureFormat,\n TextureView,\n} from '@forgeax/engine-rhi';\nimport {\n type ShaderCatalog,\n STANDARD_PHYSICAL_TEXTURE_FIELDS,\n STANDARD_PIPELINE_PARAM_SCHEMA,\n standardPhysicalTextureFields,\n} from '@forgeax/engine-shader';\nimport { derive, type ParamSchemaEntry } from '@forgeax/engine-types';\nimport { GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX } from './gpu-stage';\nimport type { PipelineSpec } from './pipeline-spec-types';\n\n// Stub PipelineSpec used by the BGL-only call sites. The dispatcher only reads\n// `spec.shader` when a registry is supplied for reflection; for caps-driven\n// kinds (pbr-view / pbr-mesh-array / pbr-instances / pbr-skin-mesh-array) and\n// for the no-registry material path the spec content is unused. A single\n// frozen stub keeps the call sites readable and is allocation-free.\n//\n// D-13 round-2 dispatcher landing — see plan-decisions D-13.\nconst BGL_ONLY_SPEC_STUB: PipelineSpec = Object.freeze({\n shader: { id: '', passKind: 'forward', variantSet: undefined },\n attachments: { colorFormats: [], depthFormat: undefined, sampleCount: 1 },\n geometry: { topology: 'triangle-list', vertexLayout: {} },\n renderState: undefined,\n}) as PipelineSpec;\n\n// ─── Device owner ───────────────────────────────────────────────────────────\n\n/** The PBR layout builder consumes only the two creation methods it owns. */\nexport type PbrPipelineDevice = Pick<RhiDevice, 'createBindGroupLayout' | 'createPipelineLayout'>;\n\n// ─── Result shape ───────────────────────────────────────────────────────────\n\nexport interface PbrPipelineLayoutBundle {\n /** Pipeline layout passed to `createRenderPipeline({ layout })`. */\n readonly pipelineLayout: PipelineLayout;\n /** view BindGroupLayout (slot 0). */\n readonly viewBgl: BindGroupLayout;\n /**\n * PBR material BindGroupLayout (slot 1) -- derived user-region entries plus\n * Skylight and transmission injection.\n */\n readonly materialBgl: BindGroupLayout;\n /** Per-entity mesh BindGroupLayout (slot 2). */\n readonly meshArrayBgl: BindGroupLayout;\n /** Per-instance storage BindGroupLayout (slot 3). */\n readonly instancesBgl: BindGroupLayout;\n /** Probe-enabled slot-3 BGL; aliases `instancesBgl` when probes are unavailable. */\n readonly probeInstancesBgl: BindGroupLayout;\n /** Same pipeline layout with the probe-enabled slot-3 BGL, when supported. */\n readonly probePipelineLayout: PipelineLayout | null;\n /**\n * Same 4 layouts in slot order. Useful for assertion sites that check the\n * pipeline-layout `bindGroupLayouts` array shape (t57 (a) + (d)).\n */\n readonly bindGroupLayouts: readonly [\n BindGroupLayout,\n BindGroupLayout,\n BindGroupLayout,\n BindGroupLayout,\n ];\n}\n\n/** Derives the Standard PBR attachment list without allocating a closed path. */\nexport function standardPbrColorFormats(\n baseFormat: TextureFormat,\n fallbackDemand: boolean,\n): readonly TextureFormat[] {\n return fallbackDemand ? [baseFormat, 'rgba16float'] : [baseFormat];\n}\n\n// ─── Base entries (round-4 SSOT) ────────────────────────────────────────────\n\n/**\n * The built-in standard-PBR material paramSchema's texture/user-region shape,\n * used as the fallback when the material BGL is built without a registry\n * (the caps-driven `buildPbrPipelineLayouts` seam). Declares the canonical\n * Standard user-region textures + a numeric UBO run; `derive()` collapses the\n * numerics into binding 0 and emits one sampler/texture pair per declared\n * texture. Physical map pairs stay outside this boot region and are appended\n * only for an authored root that declares them. The shared PBR parameter\n * contract comes from the shader package; this module only derives the GPU\n * layout.\n */\n/**\n * Build the PBR material BGL **user-region** from a paramSchema via the\n * `derive()` SSOT (D-1). The user-region is binding 0 (the run-merged material\n * UBO) followed by one sampler/texture pair per declared texture. Engine\n * injection (IBL + transmission) is appended AFTER this region by the caller via\n * `appendInjection`, with start binding = `userRegion.length` — so a 4-texture\n * custom schema (e.g. parallax + heightTexture) shifts the injection region by\n * one sampler/texture pair automatically.\n *\n * The canonical `STANDARD_PIPELINE_PARAM_SCHEMA` currently declares seven\n * non-physical textures, so this derives to binding 0 UBO + seven pairs = 15\n * entries. IBL and transmission injection are appended after that region;\n * authored physical maps are appended after the engine-owned injections.\n *\n * One material-UBO convention is layered on top of the pure `derive()` output:\n * binding 0 is patched to `{ type: 'uniform', hasDynamicOffset: true }` with\n * `VERTEX | FRAGMENT` visibility. The material UBO is bound with a per-submesh\n * dynamic offset (`render-system-record.ts setBindGroup(1, bg, [offset])`) and\n * the vertex stage reads material params, so this is required for GPU\n * validation. `derive()` stays FRAGMENT-only / no-dynamic-offset for its other\n * consumers (it is the generic SSOT, not the material-UBO authority).\n *\n * @param paramSchema - the material shader's paramSchema (defaults to the\n * built-in standard-PBR shape when omitted, for the caps-driven seam).\n */\nexport function buildPbrMaterialUserRegionEntries(\n paramSchema: readonly ParamSchemaEntry[] = STANDARD_PIPELINE_PARAM_SCHEMA,\n excludedTextureFields: readonly string[] = [],\n): GPUBindGroupLayoutEntry[] {\n const excluded = new Set(excludedTextureFields);\n for (const field of standardPhysicalTextureFields(paramSchema)) excluded.add(field);\n const derived = derive(\n excluded.size === 0\n ? paramSchema\n : paramSchema.filter(\n (entry) => !excluded.has(entry.name) || !entry.type.startsWith('texture'),\n ),\n );\n // Project the engine-owned entry shape into the DOM WebGPU descriptor. Omit\n // absent optional members so exactOptionalPropertyTypes remains true at the\n // boundary instead of leaking an `undefined` property into the descriptor.\n let entries = derived.bglEntries.map(\n (entry): GPUBindGroupLayoutEntry => ({\n binding: entry.binding,\n visibility: entry.visibility,\n ...(entry.buffer === undefined ? {} : { buffer: entry.buffer }),\n ...(entry.sampler === undefined ? {} : { sampler: entry.sampler }),\n ...(entry.texture === undefined ? {} : { texture: entry.texture }),\n ...(entry.storageTexture === undefined ? {} : { storageTexture: entry.storageTexture }),\n }),\n );\n // The record path always owns one dynamic material-UBO slot, even when an\n // authored shader declares no numeric parameters (an empty paramSchema).\n // Reserve that slot here so the IBL/transmission injection starts at the\n // same binding used by `buildPerSubmeshMaterialBg`; otherwise binding 0 in\n // the layout is a cube texture while the record path submits a UBO.\n const ubo = entries[0];\n if (ubo !== undefined && ubo.binding === 0 && ubo.buffer?.type === 'uniform') {\n entries[0] = {\n binding: 0,\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform', hasDynamicOffset: true },\n };\n } else {\n entries = [\n {\n binding: 0,\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform', hasDynamicOffset: true },\n },\n ...entries.map((entry) => ({ ...entry, binding: entry.binding + 1 })),\n ];\n }\n return entries;\n}\n\n// ─── appendInjection — generic engine-injection BGL appender (M3 / w15) ──────\n//\n// Decision anchors (plan-strategy §2):\n// - D-6 appendInjection(bgl, kind) replaces the previous hardcoded\n// emissive/AO start-binding literal (=14). The starting binding\n// number is computed from `bgl.length`, byte-equivalent to\n// `derive(schema).userRegionBindingEnd` when `bgl` is the BGL list\n// derive returned for the user paramSchema.\n// - R-1 the 14-slot user-region assumption breaks once D-3 merges UBO;\n// appendInjection lets the material BGL grow / shrink without\n// churning every injection site.\n//\n// Closed union of injection kinds (plan-strategy §2 D-6):\n// - 'shadow' reserved for future material-level shadow injection\n// (sampler_comparison + texture_depth_2d, 2 entries).\n// The active shadow bindings live in the view BGL today\n// (group(0) bindings 3..7); this kind is the seam for\n// each per-material shadow override surface a future feat\n// wires onto group(1).\n// - 'ibl' the 7 IBL / Skylight entries (irradiance / prefilter\n// cube + brdfLut 2d + 3 samplers + intensity uniform).\n// Used by `buildPbrPipelineLayouts` after the user-region\n// user paramSchema entries are emitted.\n// - 'lightmap' the 4 emissive + occlusion entries (sampler + texture\n// pair x 2). The historical name is \"emissive/AO\"; we\n// keep that meaning under the generic 'lightmap' label\n// (per-surface secondary-lighting injection) so future\n// lightmap support lands without renaming the kind.\n// - 'transmission' the engine-owned sampler + backdrop texture pair. The\n// record stage supplies a real backdrop only for the active\n// transmission pass; all other variants bind layout-safe\n// placeholders because their shaders do not read these slots.\nexport type InjectionKind = keyof typeof INJECTION_KIND_LENGTHS;\n\nconst IBL_INJECTION_LENGTH = 7;\nconst LIGHTMAP_INJECTION_LENGTH = 4;\nconst SHADOW_INJECTION_LENGTH = 2;\nconst TRANSMISSION_INJECTION_LENGTH = 2;\n\n/**\n * Append the engine-injection BGL entries for the given `kind` after the\n * user-region BGL entries, with binding numbers starting at `bgl.length`.\n *\n * The function reads `bgl.length` (NOT a hardcoded constant) so each\n * user-region size — derived from `derive(schema).userRegionBindingEnd` or\n * computed manually — flows through to the injection start binding without\n * a coupled edit.\n *\n * Returns ONLY the injected entries; the caller spreads them after `bgl`:\n *\n * ```ts\n * const merged = [...userBgl, ...appendInjection(userBgl, 'ibl')];\n * device.createBindGroupLayout({ entries: merged });\n * ```\n */\nexport function appendInjection(\n bgl: readonly GPUBindGroupLayoutEntry[],\n kind: InjectionKind,\n): GPUBindGroupLayoutEntry[] {\n const start = bgl.length;\n switch (kind) {\n case 'ibl':\n return [\n // binding start+0: irradianceMap (texture_cube)\n {\n binding: start,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: 'cube' },\n },\n // binding start+1: irradianceSampler\n {\n binding: start + 1,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' },\n },\n // binding start+2: prefilterMap (texture_cube)\n {\n binding: start + 2,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: 'cube' },\n },\n // binding start+3: prefilterSampler\n {\n binding: start + 3,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' },\n },\n // binding start+4: brdfLut (texture_2d)\n {\n binding: start + 4,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d' },\n },\n // binding start+5: brdfLutSampler\n {\n binding: start + 5,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' },\n },\n // binding start+6: uniform { intensity: f32 }\n {\n binding: start + 6,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform' },\n },\n ];\n case 'lightmap':\n return [\n // emissive sampler + texture pair\n {\n binding: start,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' },\n },\n {\n binding: start + 1,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d' },\n },\n // occlusion sampler + texture pair\n {\n binding: start + 2,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' },\n },\n {\n binding: start + 3,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d' },\n },\n ];\n case 'shadow':\n return [\n {\n binding: start,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'comparison' },\n },\n {\n binding: start + 1,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'depth', viewDimension: '2d' },\n },\n ];\n case 'transmission':\n return [\n {\n binding: start,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' },\n },\n {\n binding: start + 1,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d' },\n },\n ];\n }\n}\n\n// Closed-set length sentinels — the map is the membership owner.\nexport const INJECTION_KIND_LENGTHS = {\n shadow: SHADOW_INJECTION_LENGTH,\n ibl: IBL_INJECTION_LENGTH,\n lightmap: LIGHTMAP_INJECTION_LENGTH,\n transmission: TRANSMISSION_INJECTION_LENGTH,\n};\n\nexport function physicalTextureFields(paramSchema: readonly ParamSchemaEntry[]): readonly string[] {\n return standardPhysicalTextureFields(paramSchema);\n}\n\nexport function appendTextureInjection(\n _bgl: readonly GPUBindGroupLayoutEntry[],\n fields: readonly string[],\n): GPUBindGroupLayoutEntry[] {\n const fieldSet = new Set(fields);\n // Physical resources use the Standard root's fixed slots (26 + canonical\n // index * 2). Do not compact an authored subset: the shader template and\n // scene-index receipt share these canonical bindings, while gaps simply\n // represent physical axes omitted by the selected root contract.\n return standardPhysicalTextureFields(\n STANDARD_PIPELINE_PARAM_SCHEMA.concat(\n fields.map((name) => ({ name, type: 'texture2d' as const })),\n ),\n ).flatMap((field) => {\n if (!fieldSet.has(field)) return [];\n const canonicalIndex = STANDARD_PHYSICAL_TEXTURE_FIELDS.indexOf(field);\n const binding = 26 + canonicalIndex * 2;\n return [\n {\n binding,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' as const },\n },\n {\n binding: binding + 1,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float' as const, viewDimension: '2d' as const },\n },\n ];\n });\n}\n\n/**\n * Return the stable identity of the merged material bind-group layout.\n *\n * This is deliberately derived from the same descriptor builder consumed by\n * the device path. Callers use it to keep pipeline, bind-group, and\n * frame-local lookup caches on one layout identity even when equivalent\n * paramSchema arrays were allocated independently.\n */\nexport function materialBindGroupLayoutIdentity(\n shaderId: string,\n paramSchema: readonly ParamSchemaEntry[],\n): string {\n const descriptor = buildBindGroupLayoutDescriptor(\n {\n shader: { id: shaderId, passKind: 'forward', variantSet: undefined },\n attachments: { colorFormats: [], depthFormat: undefined, sampleCount: 1 },\n geometry: { topology: 'triangle-list', vertexLayout: {} },\n renderState: undefined,\n },\n { kind: 'pbr-material-merged', materialParamSchema: paramSchema },\n );\n // Descriptor shape alone cannot distinguish two Standard roots that expose\n // the same number of physical texture pairs under different semantic names.\n // The resource order is part of the admitted root contract, so include the\n // canonical physical projection in the cache identity while keeping the\n // actual WebGPU descriptor owned by the builder above.\n return JSON.stringify({\n entries: descriptor.entries,\n physicalTextureFields: physicalTextureFields(paramSchema),\n });\n}\n\n/**\n * Caps shape consumed by the BGL factory functions for storage-buffer vs\n * uniform-buffer branching. Mirrors the two fields the engine reads from\n * `RhiCaps` (plan D-4 + D-5).\n */\nexport interface PbrCaps {\n readonly storageBuffer: boolean;\n /**\n * Whether the selected material variant declares the optional extended\n * lighting view resources. The default keeps the historical helper shape\n * for callers that build the canonical full PBR layout; the renderer passes\n * the device/variant decision explicitly.\n */\n readonly extendedLighting?: boolean;\n /** Selects the optional binding(1) ProbeBlendRecord lane. */\n readonly probeBlend?: boolean;\n /** Whether the device can carry the optional SpotLight projector texture. */\n readonly projectorAvailable?: boolean;\n /** Omit unused backdrop slots on minimum-limit devices; physical slots stay fixed. */\n readonly transmissionBackdrop?: boolean;\n}\n\n/**\n * The view BGL entry list. binding 0 = view UBO (vertex + fragment);\n * binding 3 = directional shadowMap atlas (texture_depth_2d, vertex+fragment).\n * feat-20260613-csm-cascaded-shadow-maps: this is the CSM atlas — N\n * cascades tiled into one 2D depth texture, sampled via per-cascade UV\n * mapping in `lighting-directional.wgsl`. Single binding survives N=1..4\n * (no array-layer form; cascades live in viewport offsets per the\n * check-csm-unique-shadow-path grep gate).\n * binding 4 = shadow comparison sampler (shared by directional + point);\n * binding 5 = point shadow cube_array depth atlas (texture_depth_cube_array;\n * fragment-only). feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1.\n * binding 6 = point shadow params UBO (`array<vec4<f32>, 4>`, 64 B;\n * fragment-only). One lane per shadow-casting point light slot\n * (shadowAtlasLayer in [0, 4)) carrying `(near, far, depthBias, normalBias)`.\n * binding 7 = shadowCasterCascade UBO (16 B; vertex + fragment). Per-pass\n * cascade-index uniform consumed exclusively by `shadow_caster.wgsl` to\n * pick `view.lightViewProj_X` for the cascade currently being rasterized\n * (feat-20260613-csm-cascaded-shadow-maps M5 / w28). Forward PBR shaders\n * declare the binding via `common.wgsl` but do not reference it; WebGPU\n * still requires a populated entry on every view BG so the host writes a\n * stable singleton buffer.\n * binding 8 = spot shadow atlas (texture_depth_2d; fragment-only).\n * feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5). A single 2D depth\n * texture holding up to 4 spot shadows in a 2x2 tile grid. ALWAYS-ON (no caps\n * gate — `texture_depth_2d` is compat-safe everywhere), matching the\n * unconditional `spotShadowMap` WGSL declaration in common.wgsl. Reuses the\n * comparison sampler at binding 4 (no binding 9). Every view BG must populate\n * binding 8 (real spotShadowDepth view when spot shadows run, else a 1x1\n * fallback depth view cleared to fully-lit).\n *\n * Mirrors feat-20260519-light-casters M3 D-S1 layout +\n * feat-20260520-directional-light-shadow-mapping M2 / w14 (D-1) shadow\n * map binding +\n * feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1 BGL hookup\n * (always-on bindings 5/6 paired with the unconditional `POINT_SHADOW_AVAILABLE`\n * define registered in vite-plugin-shader) +\n * feat-20260613-csm-cascaded-shadow-maps M5 / w28 (binding 7 cascade UBO).\n * binding 10 (Points/Lines viewport UBO; always bound for the shared view\n * layout and consumed only by the dedicated points-lines shader).\n * Isolated here so M4 round-4 tests can recreate the layout.\n *\n * Local lights are not part of the view group. Standard material variants\n * consume the one Cluster payload in group(2), while this group retains only\n * camera and shadow resources.\n */\nexport function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[] {\n const entries: GPUBindGroupLayoutEntry[] = [\n {\n binding: 0,\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n // View captures use the same bind group with a per-face view slot.\n // Keeping this dynamic is also valid for the display slot at offset 0.\n buffer: { type: 'uniform', hasDynamicOffset: true },\n },\n {\n binding: 3,\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'depth', viewDimension: '2d' },\n },\n {\n binding: 4,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'comparison' },\n },\n // feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: point shadow\n // cube_array depth atlas. Bound to either the real ShadowAtlas\n // cube_array view (when point shadows are active) or a 1x1x6 fallback\n // cube_array view cleared to 1.0 (fully lit). Visibility is FRAGMENT\n // only -- the directional binding 3 is VERTEX|FRAGMENT for shadow\n // probe-debug sampling, but the cube atlas has no host-side probe path.\n {\n binding: 5,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'depth', viewDimension: 'cube-array' },\n },\n // feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: point shadow\n // params UBO. Carries `array<vec4<f32>, 4>` = 64 B with one lane per\n // shadow-casting point light slot (shadowAtlasLayer in [0, 4)). Each\n // lane stores `(near, far, depthBias, normalBias)` so the fragment-shader\n // depth-ref reconstruction (lighting-punctual.wgsl evalPointShadowed)\n // can avoid sampling DirectLightSlot for the URP path. The shared\n // DirectLightSlot metadata remains the identity owner, so binding 6 is\n // unused on HDRP shaders even though the BGL declares it (charter P4 single SSOT\n // BGL across pipelines; the HDRP variant simply doesn't reference the\n // binding in WGSL, which is allowed).\n {\n binding: 6,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform' },\n },\n // feat-20260613-csm-cascaded-shadow-maps M5 / w28: shadowCasterCascade\n // UBO (16 B). Carries the 0-based cascade index of the shadow pass\n // currently being rasterized so `shadow_caster.wgsl` can index into\n // `view.lightViewProj_X` per cascade. Shifted from binding 5 to\n // binding 7 on 2026-06-13 to make room for point-shadow bindings 5/6\n // (they predate this feat in main; CSM's slot was the optimal-yield\n // give since point-shadow needs FRAGMENT-only and the cascade UBO\n // needs vertex-stage too — keeping cascade higher avoids interleaving\n // visibility flags within the contiguous shadow-binding cluster).\n {\n binding: 7,\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform' },\n },\n // feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5): spot shadow\n // atlas. A single `texture_depth_2d` holding up to 4 spot shadows in a 2x2\n // tile grid (urp-pipeline.ts spotShadowDepth). FRAGMENT-only — the spot\n // shadow factor is reconstructed at fragment time via perspective-divide in\n // `evalSpotShadowed` (lighting-punctual.wgsl).\n //\n // ALWAYS-ON (no caps gate, unlike the point cube_array atlas at binding 5\n // which rides POINT_SHADOW_AVAILABLE): spot uses `texture_depth_2d` which is\n // compat-safe in every WebGPU profile, so the binding is unconditionally\n // declared. The matching WGSL declaration is `spotShadowMap` at @group(0)\n // binding 8 in common.wgsl (also unconditional) — the two must stay in\n // lock-step or WebGPU validation rejects the bind group at smoke time\n // (memory: BGL shape mismatch is a browser-path-only bug). No binding 9\n // sampler: spot reuses the comparison sampler at binding 4.\n // feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5): spot shadow 2D\n // atlas, the LAST view-BG binding. The per-spot fragment-read perspective\n // lightViewProj matrices that w24 originally declared at a standalone\n // binding 9 uniform buffer were folded into the View UBO (binding 0,\n // `view.spotLightViewProj`) in w25 (scope-amend webkit-fallback): the\n // standalone binding pushed the WebGL2 fallback fragment uniform-buffer\n // count to 12, over GLES 3.0's `max_uniform_buffers_per_shader_stage = 11`,\n // crashing pipeline-layout creation on the compat path (this feat's target).\n {\n binding: 8,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'depth', viewDimension: '2d' },\n },\n ];\n const extendedLighting = caps.extendedLighting ?? true;\n if (extendedLighting) {\n entries.push(\n {\n binding: 9,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' },\n },\n {\n binding: 11,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d-array' },\n },\n {\n binding: 12,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d-array' },\n },\n {\n binding: 13,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d' },\n },\n {\n binding: 14,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d' },\n },\n {\n binding: 15,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform' },\n },\n );\n } else if (caps.projectorAvailable !== false) {\n entries.push(\n {\n binding: 11,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d' },\n },\n {\n binding: 12,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' },\n },\n );\n }\n entries.push({\n binding: 10,\n visibility: GPU_SHADER_STAGE_VERTEX,\n buffer: { type: 'uniform', hasDynamicOffset: true },\n });\n return entries;\n}\n\n// ─── PBR pipeline layout factory ────────────────────────────────────────────\n\n/**\n * Build the PBR pipeline layout under D-5 round-4: 4 slots `[view,\n * material, mesh-array, instances]`; the material BGL is derived from the\n * standard material schema and engine injection chain.\n *\n * `caps.storageBuffer===false` switches the mesh-array and instances entries\n * to `uniform`; local-light resources are never part of this view group.\n *\n * Throws on each `createBindGroupLayout` / `createPipelineLayout` Result\n * failure -- the engine bootstrap path (createRenderer) wraps the call in\n * `runShimSyncStep` to fold the throw into the structured error pipe.\n */\nexport function buildPbrPipelineLayouts(\n device: PbrPipelineDevice,\n caps: PbrCaps,\n): PbrPipelineLayoutBundle {\n // D-13 round-2: 4 BGLs route through buildBindGroupLayoutDescriptor.\n // The dispatcher reads kind + caps; spec content is unused without a\n // registry (no shader-axis reflection at this seam — the 4 BGLs are\n // caps-driven literals + the deterministic Skylight + transmission merge\n // sequence that has no dependency on shader.id).\n const viewBglRes = device.createBindGroupLayout(\n buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'pbr-view', caps }),\n );\n if (!viewBglRes.ok) throw viewBglRes.error;\n\n // Material BGL: derived user region + Skylight + transmission injection.\n // The transmission start binding is computed from the post-Skylight BGL\n // length (= 22 for the canonical Standard schema) by appendInjection.\n const materialBglRes = device.createBindGroupLayout(\n buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {\n kind: 'pbr-material-merged',\n caps,\n }),\n );\n if (!materialBglRes.ok) throw materialBglRes.error;\n\n // mesh-array BGL.\n const meshArrayBglRes = device.createBindGroupLayout(\n buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'pbr-mesh-array', caps }),\n );\n if (!meshArrayBglRes.ok) throw meshArrayBglRes.error;\n\n // instances BGL.\n const instancesBglRes = device.createBindGroupLayout(\n buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {\n kind: 'pbr-instances',\n caps: { ...caps, probeBlend: false },\n }),\n );\n if (!instancesBglRes.ok) throw instancesBglRes.error;\n // ProbeBlendRecord is a storage-buffer-only ABI extension. A uniform\n // fallback cannot afford the extra fragment-stage uniform binding on\n // WebGL2/GLES, so do not even construct the probe BGL on that capability\n // route. The record stage gates the matching variant and bind group with\n // the same storage capability; aliasing the ordinary BGL keeps the bundle\n // total and makes an accidental probe request fail closed at layout select.\n const probeInstancesBglRes = caps.storageBuffer\n ? device.createBindGroupLayout(\n buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {\n kind: 'pbr-instances',\n caps: { ...caps, probeBlend: true },\n }),\n )\n : { ok: true as const, value: instancesBglRes.value };\n if (!probeInstancesBglRes.ok) throw probeInstancesBglRes.error;\n\n // Pipeline layout (4 slots).\n const layouts: readonly [BindGroupLayout, BindGroupLayout, BindGroupLayout, BindGroupLayout] = [\n viewBglRes.value,\n materialBglRes.value,\n meshArrayBglRes.value,\n instancesBglRes.value,\n ];\n const pipelineLayoutRes = device.createPipelineLayout({\n label: 'pbr-pl',\n bindGroupLayouts: layouts,\n });\n if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;\n const probeLayouts: readonly [\n BindGroupLayout,\n BindGroupLayout,\n BindGroupLayout,\n BindGroupLayout,\n ] = [viewBglRes.value, materialBglRes.value, meshArrayBglRes.value, probeInstancesBglRes.value];\n let probePipelineLayout: PipelineLayout | null = null;\n if (caps.storageBuffer) {\n const probePipelineLayoutRes = device.createPipelineLayout({\n label: 'pbr-probe-pl',\n bindGroupLayouts: probeLayouts,\n });\n if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;\n probePipelineLayout = probePipelineLayoutRes.value;\n }\n\n return {\n pipelineLayout: pipelineLayoutRes.value,\n viewBgl: viewBglRes.value,\n materialBgl: materialBglRes.value,\n meshArrayBgl: meshArrayBglRes.value,\n instancesBgl: instancesBglRes.value,\n probeInstancesBgl: probeInstancesBglRes.value,\n probePipelineLayout,\n bindGroupLayouts: layouts,\n };\n}\n\n// ─── PBR skin material-shader identifier (SSOT) ────────────────────────────\n\n/**\n * SSOT for the skin material shader's registered identifier. The shader\n * package registers under this string (see register-default-standard-pbr-skin.ts\n * `RESERVED_ID`); runtime dispatch sites import this constant rather than\n * carrying a literal so a future rename is a one-line change. AC-09 grep\n * gate: the body of `selectPipelineLayoutForVariant` MUST NOT contain a\n * literal `'forgeax::pbr-skin'` -- callers map this constant to\n * `LayoutKind = 'pbr-skin'` upstream.\n */\nexport const SKIN_MATERIAL_SHADER_ID = 'forgeax::pbr-skin' as const;\nexport const SHADOW_CASTER_SHADER_ID = 'forgeax::default-shadow-caster' as const;\n\n// Authored Standard templates are published under a unique module id for each\n// root contract. Keep the family marker in the id so every downstream render\n// owner (extract, layout, and record) can make the same Standard-vs-custom and\n// rigid-vs-skinned decision without a second registry or a runtime shader\n// inspection pass.\nconst AUTHORED_STANDARD_ID_RE = /::(?:standard|pbr-skin)(?:-|$)/;\n\nexport function isStandardPbrSkinMaterialShader(shaderId: string | undefined): boolean {\n return (\n shaderId === SKIN_MATERIAL_SHADER_ID ||\n shaderId === 'forgeax::default-standard-pbr-skin' ||\n (shaderId !== undefined && /::pbr-skin(?:-|$)/.test(shaderId))\n );\n}\n\nexport function shadowCasterVariantSet(\n storageBuffer: boolean,\n skinned: boolean,\n gpuDrivenSceneIndex = false,\n alphaMask = false,\n vertexColorAvailable = false,\n): string {\n const skinningDisabled = !skinned;\n const defines: Record<string, boolean> = {\n ALPHA_MASK: alphaMask,\n GPU_DRIVEN_SCENE_INDEX_AVAILABLE: gpuDrivenSceneIndex,\n GPU_DRIVEN_SCENE_INDEX_EXPLICIT: false,\n SKINNING_DISABLED: skinningDisabled,\n STORAGE_BUFFER_AVAILABLE: storageBuffer,\n };\n if (vertexColorAvailable) defines.VERTEX_COLOR_AVAILABLE = true;\n return Object.entries(defines)\n .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))\n .map(([name, value]) => `${name}=${String(value)}`)\n .join('+');\n}\n\nexport function isSkinnedShadowCasterVariant(\n materialShaderId: string | undefined,\n variantSet: string | undefined,\n): boolean {\n return (\n materialShaderId === SHADOW_CASTER_SHADER_ID &&\n variantSet?.includes('SKINNING_DISABLED=false') === true\n );\n}\n\nexport type PipelineGroup2Contract = 'mesh' | 'skin' | 'cluster' | 'skin-cluster';\n\n/** Resolve group(2) from the composed WGSL artifact used to build the PSO. */\nexport function resolvePipelineGroup2Contract(source: string): PipelineGroup2Contract {\n const withoutComments = source.replace(/\\/\\*[\\s\\S]*?\\*\\//gu, '').replace(/\\/\\/.*$/gmu, '');\n const bindings = [\n ...withoutComments.matchAll(/@group\\s*\\(\\s*2\\s*\\)\\s*@binding\\s*\\(\\s*(\\d+)\\s*\\)/gu),\n ].map((match) => Number(match[1]));\n const hasSkinBindings = bindings.includes(1) || bindings.includes(2);\n const hasClusterBindings = bindings.some((binding) => binding >= 3);\n if (hasSkinBindings && hasClusterBindings) return 'skin-cluster';\n if (hasSkinBindings) return 'skin';\n if (hasClusterBindings) return 'cluster';\n return 'mesh';\n}\n\n/** Returns true for the engine-shipped standard-PBR material shader family. */\nexport function isStandardPbrMaterialShader(shaderId: string | undefined): boolean {\n return (\n shaderId === 'forgeax::default-standard-pbr' ||\n shaderId === SKIN_MATERIAL_SHADER_ID ||\n shaderId === 'forgeax::default-standard-pbr-skin' ||\n (shaderId !== undefined && AUTHORED_STANDARD_ID_RE.test(shaderId))\n );\n}\n\n/**\n * Return true only for the two engine-owned Standard roots. Authored Standard\n * aliases intentionally remain outside this set: their cooked root schema may\n * omit transmission or other optional resources, so their compact user-region\n * layout must be derived from that artifact instead of borrowing the boot\n * layout's reserved slots.\n */\nexport function isCanonicalStandardPbrMaterialShader(shaderId: string | undefined): boolean {\n return (\n shaderId === 'forgeax::default-standard-pbr' ||\n shaderId === SKIN_MATERIAL_SHADER_ID ||\n shaderId === 'forgeax::default-standard-pbr-skin'\n );\n}\n\n// ─── PBR skin pipeline layout factory (bug-20260611) ───────────────────────\n//\n// The skin material shader (`forgeax::pbr-skin`, registered by\n// `register-default-standard-pbr-skin.ts`) needs the same 4-slot layout shape\n// as standard PBR EXCEPT for slot 2: its mesh-array BGL declares **2**\n// dynamic-offset entries (binding 0 = meshes, binding 1 = palette) versus\n// standard PBR's single binding 0. Without a dedicated pipeline layout the\n// skin shader's `@group(2) @binding(1) palette : array<mat4x4<f32>>` reference\n// trips a `Binding doesn't exist in [BindGroupLayoutInternal \"pbr-mesh-array-bgl\"]`\n// validation error in `device.createRenderPipeline`, surfaced as\n// `RhiError limit-exceeded` and an invalid command buffer (Playwright TDD trace\n// captured 2026-06-11 in apps/hello/skin).\n//\n// The factory **reuses** view / material / instances BGL handles produced by\n// `buildPbrPipelineLayouts` (charter P4: a single SSOT BGL for each slot the\n// shapes actually share) and only creates a new mesh-array BGL + new pipeline\n// layout. This keeps the per-binding-shape SSOT in one place and avoids an\n// alternate skin-only material BGL (the skin shader's group(0) and group(1)\n// are byte-for-byte the standard-PBR contract).\n\n/**\n * Build the PBR skin pipeline layout (4 slots `[view, material,\n * mesh-array(3-entry), instances]`). View / material / instances BGLs are\n * shared with the standard-PBR layout (passed in via `pbr` bundle); the only\n * new BGL is the 3-entry mesh-array slot for `meshes` + current/previous\n * `palette` buffers.\n *\n * Throws on each `createBindGroupLayout` / `createPipelineLayout` Result\n * failure -- the engine bootstrap path wraps the call in `runShimSyncStep`\n * to fold the throw into the structured error pipe.\n */\nexport function buildPbrSkinLayouts(\n device: PbrPipelineDevice,\n caps: PbrCaps,\n pbr: PbrPipelineLayoutBundle,\n): PbrPipelineLayoutBundle {\n // 3-entry mesh-array BGL: binding 0 meshes + binding 1 current palette\n // + binding 2 previous palette. All use dynamic offsets for the same\n // per-entity window contract.\n const skinMeshArrayBglRes = device.createBindGroupLayout(\n buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {\n kind: 'pbr-skin-mesh-array',\n caps,\n }),\n );\n if (!skinMeshArrayBglRes.ok) throw skinMeshArrayBglRes.error;\n\n const layouts: readonly [BindGroupLayout, BindGroupLayout, BindGroupLayout, BindGroupLayout] = [\n pbr.viewBgl,\n pbr.materialBgl,\n skinMeshArrayBglRes.value,\n pbr.instancesBgl,\n ];\n const pipelineLayoutRes = device.createPipelineLayout({\n label: 'pbr-skin-pl',\n bindGroupLayouts: layouts,\n });\n if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;\n const probeLayouts: readonly [\n BindGroupLayout,\n BindGroupLayout,\n BindGroupLayout,\n BindGroupLayout,\n ] = [pbr.viewBgl, pbr.materialBgl, skinMeshArrayBglRes.value, pbr.probeInstancesBgl];\n let probePipelineLayout: PipelineLayout | null = null;\n if (caps.storageBuffer) {\n const probePipelineLayoutRes = device.createPipelineLayout({\n label: 'pbr-skin-probe-pl',\n bindGroupLayouts: probeLayouts,\n });\n if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;\n probePipelineLayout = probePipelineLayoutRes.value;\n }\n\n return {\n pipelineLayout: pipelineLayoutRes.value,\n viewBgl: pbr.viewBgl,\n materialBgl: pbr.materialBgl,\n meshArrayBgl: skinMeshArrayBglRes.value,\n instancesBgl: pbr.instancesBgl,\n probeInstancesBgl: pbr.probeInstancesBgl,\n probePipelineLayout,\n bindGroupLayouts: layouts,\n };\n}\n\n/**\n * Build the dedicated slot-3 layout used by scene-index GPU-driven draws.\n *\n * Direct material draws deliberately keep `pbr-instances-bgl` at binding(0),\n * and ProbeBlend deliberately owns binding(1). The scene-index stream is\n * therefore a separate BGL at binding(2), rather than an optional entry added\n * to the direct layout. This keeps every bind group complete for its shader\n * and prevents a direct draw from having to bind a dummy visible stream.\n */\nexport function buildGpuDrivenPbrInstancesBindGroupLayout(\n device: PbrPipelineDevice,\n caps: PbrCaps,\n): BindGroupLayout {\n if (!caps.storageBuffer) {\n throw new Error('GPU-driven PBR instances layout requires storage-buffer capability');\n }\n const result = device.createBindGroupLayout(\n buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {\n kind: 'pbr-gpu-driven-instances',\n caps,\n }),\n );\n if (!result.ok) throw result.error;\n return result.value;\n}\n\n/** Build the four-slot rigid scene-index pipeline layout. */\nexport function buildGpuDrivenPbrPipelineLayout(\n device: PbrPipelineDevice,\n pbr: PbrPipelineLayoutBundle,\n gpuDrivenInstancesBgl: BindGroupLayout,\n): PipelineLayout {\n const result = device.createPipelineLayout({\n label: 'pbr-gpu-driven-pl',\n bindGroupLayouts: [pbr.viewBgl, pbr.materialBgl, pbr.meshArrayBgl, gpuDrivenInstancesBgl],\n });\n if (!result.ok) throw result.error;\n return result.value;\n}\n\n/** Build the four-slot skinned scene-index pipeline layout. */\nexport function buildGpuDrivenPbrSkinPipelineLayout(\n device: PbrPipelineDevice,\n pbrSkin: PbrPipelineLayoutBundle,\n gpuDrivenInstancesBgl: BindGroupLayout,\n): PipelineLayout {\n const result = device.createPipelineLayout({\n label: 'pbr-skin-gpu-driven-pl',\n bindGroupLayouts: [\n pbrSkin.viewBgl,\n pbrSkin.materialBgl,\n pbrSkin.meshArrayBgl,\n gpuDrivenInstancesBgl,\n ],\n });\n if (!result.ok) throw result.error;\n return result.value;\n}\n\n/** Project the canonical group(2) resources for a PBR skin draw. */\nexport function createPbrSkinMeshBindGroupEntries(\n meshBuffer: Buffer,\n meshSize: number,\n paletteBuffer: Buffer,\n paletteWindowBytes: number,\n): BindGroupEntry[] {\n return [\n {\n binding: 0,\n resource: { kind: 'buffer', value: { buffer: meshBuffer, offset: 0, size: meshSize } },\n },\n ...[1, 2].map((binding) => ({\n binding,\n resource: {\n kind: 'buffer' as const,\n value: {\n buffer: paletteBuffer,\n offset: 0,\n size: paletteWindowBytes,\n },\n },\n })),\n ];\n}\n\n/** Project all dynamic offsets for the canonical PBR skin group(2) shape. */\nexport function pbrSkinMeshDynamicOffsets(\n meshOffset: number,\n paletteOffset: number,\n): readonly [number, number, number] {\n return [meshOffset, paletteOffset, paletteOffset];\n}\n\n// ─── Unlit material BGL factory ─────────────────────────────────────────────\n\n/**\n * Build a stand-alone 7-entry unlit material BGL. Round-4 D-5 keeps unlit\n * material BG isolated from Skylight binding 7..13 -- unlit demos do not\n * pay for IBL state. The unlit pipeline still binds material at slot 1,\n * just with a 7-entry layout.\n *\n * Note: at the moment the runtime still routes both unlit + standard\n * through a single 14-entry pipeline layout; the unlit material BG\n * carries fallback identity resources at binding 7..13. This factory is\n * exported as a future-proof seam for the moment when unlit demos own\n * their own pipeline layout (t57 (e) test pins the contract today so the\n * eventual split has a green target).\n */\nexport function buildUnlitMaterialBgl(device: PbrPipelineDevice): BindGroupLayout {\n const res = device.createBindGroupLayout(\n buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'unlit-material' }),\n );\n if (!res.ok) throw res.error;\n return res.value;\n}\n\n// ─── Material BG assembly helpers (unlit) ───────────────────────────────────\n\n/**\n * Inputs for `buildUnlitMaterialBindGroupEntries`. The fields mirror the\n * record-stage's local variables; isolating the assembler here lets t58\n * (e) test exercise the contract without recreating the entire record\n * stage.\n */\nexport interface UnlitMaterialBindGroupEntryInputs {\n readonly materialUniform: Buffer;\n readonly materialOffset: number;\n readonly materialSize: number;\n readonly defaultSampler: Sampler;\n readonly baseColorView: TextureView;\n readonly defaultWhiteView: TextureView;\n}\n\n/**\n * Build the 7 BindGroupEntry values for the unlit material BG (binding\n * 0..6). Output flows into `device.createBindGroup({ layout:\n * unlitMaterialBgl, entries })`.\n */\nexport function buildUnlitMaterialBindGroupEntries(\n inputs: UnlitMaterialBindGroupEntryInputs,\n): BindGroupEntry[] {\n return [\n {\n binding: 0,\n resource: {\n kind: 'buffer' as const,\n value: {\n buffer: inputs.materialUniform,\n offset: inputs.materialOffset,\n size: inputs.materialSize,\n },\n },\n },\n { binding: 1, resource: { kind: 'sampler' as const, value: inputs.defaultSampler } },\n { binding: 2, resource: { kind: 'textureView' as const, value: inputs.baseColorView } },\n { binding: 3, resource: { kind: 'sampler' as const, value: inputs.defaultSampler } },\n { binding: 4, resource: { kind: 'textureView' as const, value: inputs.defaultWhiteView } },\n { binding: 5, resource: { kind: 'sampler' as const, value: inputs.defaultSampler } },\n { binding: 6, resource: { kind: 'textureView' as const, value: inputs.defaultWhiteView } },\n ];\n}\n\n// Surface re-export so consumers can build a complete BindGroup pipeline\n// without reaching into multiple modules.\nexport type { BindGroup };\n\n// ─── feat-20260625 M3 / w10 — sprite-pass variantSet selector ────────────────\n//\n// Plan-strategy D-1 + D-4: when an entity carries `SpriteInstances` the\n// sprite-pass record stage must pick the `PER_INSTANCE_REGION=true` sprite\n// shader variant compiled in M2 (w7) so the WGSL `InstanceData` struct\n// includes the per-instance `region: vec4<f32>` field and reads region from\n// the interleaved 80B-per-instance buffer (not from the material UBO).\n//\n// Non-`SpriteInstances` sprite entities (e.g. the sprite-atlas demo) keep\n// the default variant where `PER_INSTANCE_REGION` is undefined and the\n// shader's `#else` branch reads region from material UBO — preserving\n// existing behaviour (plan-strategy D-4 \"pbr / unlit / sprite-atlas\n// behaviour unchanged\" / requirements Edge Cases).\n//\n// Variant set string format mirrors the Standard boot variant /\n// HDRP variant set string idiom in `pipeline-spec.ts` (`+`-separated kv\n// pairs); the record stage threads this string through the per-shader\n// pipeline-cache key + lazy-build `getMaterialShaderPipeline` lookup.\n\n/**\n * variantSet string fired into the sprite-pass pipeline cache when the\n * entity carries `SpriteInstances` (plan-strategy D-1 interleaved single\n * buffer + D-4 axis on `sprite.wgsl`).\n *\n * bug-20260708 M2 (c): aligned with the canonical all-true variant key\n * `''` — sprite's manifest emits `{PIR:true, SBA:true}` under the empty-\n * string key (all variant axes true → canonical). The runtime's\n * `getMaterialShaderPipeline` variant-substitution branch\n * (`createRenderer.ts:1730`) resolves this via\n * `findVariantByKey(msEntry, '')` returning the 5653B PIR=true variant.\n * Combined with the `cacheKeyOf` sentinel `~` (bug-20260708 M2 (b)) this\n * value produces a cache key distinct from the `variantSet=undefined`\n * character/default path (which now resolves to the PIR=false 5575B boot-\n * registered variant). Sprite pipeline layout routing is anchored via\n * `LayoutKind='sprite-urp'` so `variantSet=''` here does NOT trigger the\n * HDRP-layout branch of `selectPipelineLayoutForVariant` (research R-12\n * flow; plan-strategy §4 R-1' guard).\n */\nexport const SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET = '';\n\n// BglKind dispatch (M3 / D-13) — closed union of BGL shapes the runtime ships\n// ══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Closed union of bind-group-layout shapes the runtime constructs.\n *\n * Each kind names one physically distinct BGL the runtime has historically\n * built by hand. {@link buildBindGroupLayoutDescriptor} dispatches on this\n * union so every `device.createBindGroupLayout(...)` call site shares one\n * SSOT for entries / labels (plan-strategy §3.2; D-13 round-2 decision).\n *\n * Three groups by derivation source:\n * 1. Shader-derived (paramSchema reflection + injection chain):\n * - `'pbr-material-merged'` — derived user region + Skylight 7 + transmission 2\n * - `'unlit-material'` — 7 entries: base PBR material only (no inject)\n * - `'hdrp-7-slot'` — 7 entries (binding 0 + 3..8): HDRP cluster + SSAO group(2) BGL\n * 2. Caps-driven literal shapes (no shader):\n * - `'pbr-view'` — camera/shadow bindings, optional projector\n * texture/sampler (11/12), and the Points/Lines UBO (10). Local lights\n * are carried exclusively by the Standard Cluster group(2).\n * (directional 3/4, point 5/6, cascade 7, spot atlas 8; the former\n * spot lightViewProj matrices moved into the View UBO)\n * - `'pbr-mesh-array'` — 1 entry: per-entity mesh SSBO (dynamic-offset)\n * - `'pbr-instances'` — 2 entries: per-instance SSBO plus the compact\n * visible-item index stream (the second entry is used only by the\n * scene-index vertex entry and shares the frame's instance bind group)\n * - `'pbr-skin-mesh-array'` — 3 entries: meshes + current/previous palette\n * 3. Attachment-driven (fullscreen post-process):\n * - `'fullscreen-post'` — 2 entries: input texture + sampler. The texture\n * `sampleType` is derived from `spec.attachments` (plan §R3 fix):\n * `'depth32float'` → `'depth'`; `'r32float'` → `'unfilterable-float'`;\n * else → `'float'`.\n * - `'fullscreen-post-with-params'` — 3 entries: the same texture@0 +\n * sampler@1 as `'fullscreen-post'`, plus a `buffer@2` uniform for the\n * per-frame params UBO (feat-20260621 D-2: `entry.params !== undefined`\n * passes route here; the layout stays group(1), q3=B). `'fullscreen-post'`\n * stays byte-identical so param-less consumers degrade with no change.\n * - `'fullscreen-post-with-scene-depth-msaa'` — the depth-read layout with\n * `texture.multisampled=true`, selected for a 4-sample scene depth target.\n */\nexport type BglKind =\n | 'pbr-view'\n | 'pbr-material-merged'\n | 'pbr-mesh-array'\n | 'pbr-instances'\n | 'pbr-gpu-driven-instances'\n | 'pbr-skin-mesh-array'\n | 'unlit-material'\n | 'hdrp-7-slot'\n | 'fullscreen-post'\n | 'fullscreen-post-with-params'\n | 'fullscreen-post-with-scene-depth'\n | 'fullscreen-post-with-scene-depth-msaa';\n\n/**\n * Output shape of {@link buildBindGroupLayoutDescriptor}: matches the RHI\n * `BindGroupLayoutDescriptor` (label + entries with `ExplicitUndefined`) so\n * the result can be passed directly to `device.createBindGroupLayout(...)`.\n *\n * `entries` is a mutable `Array` to match `GPUBindGroupLayoutDescriptor`\n * (WebGPU types declare it mutable). Callers MUST treat the array as\n * read-only — the dispatcher freezes neither the array nor its entries\n * for hot-path performance.\n */\nexport interface BindGroupLayoutDescriptorOutput {\n readonly label: string | undefined;\n readonly entries: GPUBindGroupLayoutEntry[];\n}\n\n/** Build the canonical HDRP group(2) bind-group layout. */\nexport function createHdrpBindGroupLayoutDescriptor(): BindGroupLayoutDescriptorOutput {\n const meshBufType: GPUBufferBindingType = 'read-only-storage';\n const clusterBufType: GPUBufferBindingType = 'read-only-storage';\n return {\n label: 'hdrp-unified-bgl-group2',\n entries: [\n {\n binding: 0,\n // Standard fragment lighting (transmission/refraction and clustered\n // evaluation) reads the same mesh transform window as the vertex\n // stage. Keep this visibility in the HDRP descriptor aligned with\n // the URP mesh-array descriptor; restricting it to vertex makes the\n // HDRP pipeline invalid when fs_main accesses `meshes[0]`.\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: meshBufType, hasDynamicOffset: true },\n },\n // Bindings 1 and 2 stay absent for the URP physical isolation gap.\n {\n binding: 3,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: clusterBufType, hasDynamicOffset: false },\n },\n {\n binding: 4,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: clusterBufType, hasDynamicOffset: false },\n },\n {\n binding: 5,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: clusterBufType, hasDynamicOffset: false },\n },\n {\n binding: 6,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform', hasDynamicOffset: false },\n },\n {\n binding: 7,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d', multisampled: false },\n },\n {\n binding: 8,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'filtering' },\n },\n ],\n };\n}\n\n/** Build the HDRP group(2) layout for the clustered skin variant. */\nexport function createHdrpSkinBindGroupLayoutDescriptor(): BindGroupLayoutDescriptorOutput {\n const base = createHdrpBindGroupLayoutDescriptor();\n const baseEntries = base.entries;\n if (baseEntries === undefined || baseEntries[0] === undefined) {\n throw new Error('HDRP base group(2) layout must declare mesh binding 0');\n }\n const paletteType: GPUBufferBindingType = 'read-only-storage';\n return {\n label: 'hdrp-skin-unified-bgl-group2',\n entries: [\n baseEntries[0],\n {\n binding: 1,\n visibility: GPU_SHADER_STAGE_VERTEX,\n buffer: { type: paletteType, hasDynamicOffset: true },\n },\n {\n binding: 2,\n visibility: GPU_SHADER_STAGE_VERTEX,\n buffer: { type: paletteType, hasDynamicOffset: true },\n },\n ...baseEntries.slice(1),\n ],\n };\n}\n\n/**\n * Build a `GPUBindGroupLayoutDescriptor` from a PipelineSpec, dispatching on\n * `options.kind` to one of 9 closed BGL shapes (D-13 round-2).\n *\n * Shader-derived kinds (`'pbr-material-merged'` / `'unlit-material'` /\n * `'hdrp-7-slot'`) require `options.registry` to look up the shader entry\n * and reflect its `paramSchema` via {@link deriveBglShapeFromShader}; they\n * compose the per-entry injection chain (Skylight + transmission for material;\n * HDRP variantSet for cluster-forward).\n *\n * Caps-driven kinds (`'pbr-view'` / `'pbr-mesh-array'` / `'pbr-instances'` /\n * `'pbr-skin-mesh-array'`) require `options.caps` for the storage-buffer\n * vs uniform-buffer fallback (RhiCaps.storageBuffer; PBR feat-20260526 M3 /\n * w9). They are wholly determined by the caps shape.\n *\n * Attachment-driven kind (`'fullscreen-post'`) reads\n * `spec.attachments.depthFormat` and `spec.attachments.colorFormats[0]` to\n * pick the texture binding's `sampleType` (R3 fix: `'depth32float'` → `'depth'`,\n * `'r32float'` → `'unfilterable-float'`, else → `'float'`).\n *\n * @param spec - the pipeline spec (axis source for reflection / caps fallback)\n * @param options.kind - which BGL shape to build (closed {@link BglKind} union)\n * @param options.registry - ShaderCatalog for shader-derived kinds\n * @param options.caps - caps shape for caps-driven kinds (storageBuffer)\n * @returns a WebGPU bind-group-layout descriptor (entries + label)\n * @see plan-strategy §3.2 · plan-decisions D-13 · requirements AC-02\n */\n/**\n * Resolve the material paramSchema for a per-shader user-region BGL derivation.\n *\n * Priority (D-1): explicit `options.materialParamSchema` > registry lookup of\n * `spec.shader.id` > `undefined` (the user-region builder then falls back to\n * the built-in standard-PBR 4-texture schema, whose user region is 9 entries).\n */\nfunction resolveMaterialParamSchema(\n spec: PipelineSpec,\n options: { registry?: ShaderCatalog; materialParamSchema?: readonly ParamSchemaEntry[] },\n): readonly ParamSchemaEntry[] | undefined {\n if (options.materialParamSchema !== undefined) return options.materialParamSchema;\n if (options.registry !== undefined) {\n const lookup = options.registry.findMaterialArtifact(spec.shader.id);\n if (lookup.ok) return lookup.value.paramSchema;\n }\n return undefined;\n}\n\nexport function buildBindGroupLayoutDescriptor(\n spec: PipelineSpec,\n options: {\n kind: BglKind;\n registry?: ShaderCatalog;\n caps?: PbrCaps;\n /**\n * Material paramSchema for the per-shader user-region derivation\n * (`'pbr-material-merged'` / `'unlit-material'`). When supplied it is the\n * authoritative source for the user-region BGL shape (D-1); when omitted,\n * `buildPbrMaterialUserRegionEntries` falls back to the built-in\n * standard-PBR 4-texture schema (user region is 9 entries), so\n * the caps-driven `buildPbrPipelineLayouts` seam keeps working unchanged.\n * A registry + resolvable shader id takes precedence over this field.\n */\n materialParamSchema?: readonly ParamSchemaEntry[];\n },\n): BindGroupLayoutDescriptorOutput {\n switch (options.kind) {\n case 'pbr-view': {\n const caps = options.caps ?? { storageBuffer: true };\n return {\n label: 'pbr-view-bgl',\n entries: buildPbrViewBglEntries(caps),\n };\n }\n case 'pbr-mesh-array': {\n const caps = options.caps ?? { storageBuffer: true };\n const meshBufType: GPUBufferBindingType = caps.storageBuffer\n ? 'read-only-storage'\n : 'uniform';\n // sprite-lit's fragment stage does not read the mesh SSBO -- worldPos\n // is carried through the VsOut interpolant. Visibility is kept widened\n // to VERTEX|FRAGMENT because the BGL JSON is compared byte-identically\n // across the sprite / sprite-lit / PBR pipelines that share this\n // descriptor; narrowing here would change every sibling pipeline's\n // BGL fingerprint. WebGPU rejects createRenderPipeline when a fragment\n // stage accesses a binding whose BGL visibility excludes FRAGMENT --\n // widening is permissive (validation-only, no perf cost).\n return {\n label: 'pbr-mesh-array-bgl',\n entries: [\n {\n binding: 0,\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: meshBufType, hasDynamicOffset: true },\n },\n ],\n };\n }\n case 'pbr-instances': {\n const caps = options.caps ?? { storageBuffer: true };\n const meshBufType: GPUBufferBindingType = caps.storageBuffer\n ? 'read-only-storage'\n : 'uniform';\n const entries: GPUBindGroupLayoutEntry[] = [\n {\n binding: 0,\n visibility: GPU_SHADER_STAGE_VERTEX,\n buffer: { type: meshBufType, hasDynamicOffset: false },\n },\n ...(caps.probeBlend === true\n ? [\n {\n // Per-object fragment lane; the record is always exactly 160B.\n binding: 1,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: meshBufType, hasDynamicOffset: true },\n },\n ]\n : []),\n ];\n return {\n label: caps.probeBlend === true ? 'pbr-probe-instances-bgl' : 'pbr-instances-bgl',\n entries: entries.map((entry) =>\n entry.binding === 0\n ? {\n ...entry,\n // Standard transmission reads the same per-instance transform in\n // fs_main to convert glTF unit-space thickness into world metres.\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n }\n : entry,\n ),\n };\n }\n case 'pbr-gpu-driven-instances': {\n const caps = options.caps ?? { storageBuffer: true };\n const meshBufType: GPUBufferBindingType = caps.storageBuffer\n ? 'read-only-storage'\n : 'uniform';\n // GPU-driven scene-index draws use a physically distinct slot-3 layout.\n // The ordinary instances BGL intentionally stays one-entry for direct\n // draws, while ProbeBlend owns binding(1). Keep the compact visible\n // `(meshRow, materialRow)` stream at binding(2) so a future probe-enabled\n // GPU variant can coexist without colliding with the probe record.\n return {\n label: 'pbr-gpu-driven-instances-bgl',\n entries: [\n {\n binding: 0,\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: meshBufType, hasDynamicOffset: false },\n },\n {\n // ShadowCaster's scene-index entry still reads the visible row\n // through binding(1). Keep this alias in the dedicated layout so\n // the shared visible bind group can serve both the Standard PBR\n // (binding(2)) and depth-only shadow (binding(1)) consumers.\n binding: 1,\n visibility: GPU_SHADER_STAGE_VERTEX,\n buffer: { type: meshBufType, hasDynamicOffset: false },\n },\n {\n binding: 2,\n visibility: GPU_SHADER_STAGE_VERTEX,\n buffer: { type: meshBufType, hasDynamicOffset: false },\n },\n ],\n };\n }\n case 'pbr-skin-mesh-array': {\n const caps = options.caps ?? { storageBuffer: true };\n const meshBufType: GPUBufferBindingType = caps.storageBuffer\n ? 'read-only-storage'\n : 'uniform';\n return {\n label: 'pbr-skin-mesh-array-bgl',\n entries: [\n {\n binding: 0,\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: meshBufType, hasDynamicOffset: true },\n },\n {\n binding: 1,\n visibility: GPU_SHADER_STAGE_VERTEX,\n buffer: { type: meshBufType, hasDynamicOffset: true },\n },\n {\n binding: 2,\n visibility: GPU_SHADER_STAGE_VERTEX,\n buffer: { type: meshBufType, hasDynamicOffset: true },\n },\n ],\n };\n }\n case 'pbr-material-merged': {\n // Material BGL: per-shader user-region (derive(paramSchema).bglEntries)\n // + IBL injection (7) + transmission injection (2). The user-region\n // size is the only variable; injection start = userRegion.length so a\n // custom schema shifts IBL/transmission by its sampler/texture pairs.\n // The built-in standard-PBR schema is 17 + 7 + 2 = 26 entries;\n // clearcoat texture pairs are derived from the effective root schema.\n //\n // Schema source priority (D-1): explicit materialParamSchema option >\n // registry lookup of spec.shader.id > built-in standard-PBR fallback.\n const resolvedSchema = resolveMaterialParamSchema(spec, options);\n const effectiveSchema = resolvedSchema ?? STANDARD_PIPELINE_PARAM_SCHEMA;\n const physicalFields = physicalTextureFields(effectiveSchema);\n // Standard's built-in shader keeps the transmission user-region slots\n // reserved even when a particular root omits those values. Physical\n // maps extend that canonical region; they must not compact the IBL\n // bindings to the smaller authored subset. A compact user region is\n // still correct for authored (non-engine) material shaders.\n const userRegionSchema = isCanonicalStandardPbrMaterialShader(spec.shader.id)\n ? STANDARD_PIPELINE_PARAM_SCHEMA\n : effectiveSchema;\n const userRegion = buildPbrMaterialUserRegionEntries(userRegionSchema);\n const afterIbl = [...userRegion, ...appendInjection(userRegion, 'ibl')];\n const afterTransmission = [...afterIbl, ...appendInjection(afterIbl, 'transmission')];\n const merged = [\n ...(options.caps?.transmissionBackdrop === false ? afterIbl : afterTransmission),\n ...appendTextureInjection(afterTransmission, physicalFields),\n ];\n // Scene-index Standard variants consume one producer-owned material row\n // after the complete fixed physical range. Keeping it at binding 46\n // prevents any authored physical subset from aliasing the row.\n if (options.caps?.storageBuffer ?? true) {\n merged.push({\n binding: 46,\n visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'read-only-storage', hasDynamicOffset: false },\n });\n }\n return {\n label: 'pbr-material-skylight-bgl',\n entries: [\n ...merged,\n {\n binding: 47,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'float', viewDimension: 'cube' },\n },\n ],\n };\n }\n case 'unlit-material': {\n // Unlit material BGL: per-shader user-region only. No IBL/transmission\n // injection (D-5 round-4: unlit demos do not pay for IBL state).\n const resolvedSchema = resolveMaterialParamSchema(spec, options);\n return {\n label: 'unlit-material-bgl',\n entries: buildPbrMaterialUserRegionEntries(resolvedSchema),\n };\n }\n case 'hdrp-7-slot': {\n // Standard unified BGL for group(2): 9 entries (binding 0 + 3..8).\n // Cluster variants are admitted only when storage buffers are present;\n // there is no uniform-backed cluster shape.\n const desc = createHdrpBindGroupLayoutDescriptor();\n return {\n label: desc.label ?? 'hdrp-unified-bgl-group2',\n entries: [...(desc.entries ?? [])],\n };\n }\n case 'fullscreen-post': {\n // Fullscreen post-process BGL: 2 entries (input texture + sampler).\n // R3 fix: derive sampleType from spec.attachments. Depth attachments\n // (depth32float) need `sampleType: 'depth'`; r32float needs\n // `'unfilterable-float'`; everything else (rgba8unorm-srgb, rgba16float,\n // bgra8unorm, …) is filterable `'float'`.\n return {\n label: 'fullscreen-post-bgl',\n entries: buildFullscreenPostInputEntries(spec),\n };\n }\n case 'fullscreen-post-with-params': {\n // feat-20260621 D-2: the same input texture@0 + sampler@1 as\n // 'fullscreen-post', plus binding 2 = per-frame params UBO (uniform).\n // The first two entries reuse buildFullscreenPostInputEntries so the\n // sampleType derivation stays a single SSOT; 'fullscreen-post' is\n // untouched (param-less zero-regression, R-A7).\n return {\n label: 'fullscreen-post-with-params-bgl',\n entries: [\n ...buildFullscreenPostInputEntries(spec),\n {\n binding: 2,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform' },\n },\n ],\n };\n }\n case 'fullscreen-post-with-scene-depth': {\n // plan-strategy D-3: 5-entry BGL for post-process passes that read the\n // camera scene depth. color@0 + sampler@1 reuse buildFullscreenPostInputEntries\n // (float+filtering for color). depthTex@3 uses `sampleType: 'depth'` and\n // `dimension: '2d'`; depthSampler@4 uses `type: 'non-filtering'` (nearest\n // + clamp-to-edge, D-2 — NOT comparison). params@2 is always present\n // (uniform) to avoid a 2x2 kind explosion per D-3.\n return {\n label: 'fullscreen-post-with-scene-depth-bgl',\n entries: [\n ...buildFullscreenPostInputEntries(spec),\n {\n binding: 2,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform' },\n },\n {\n binding: 3,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'depth', viewDimension: '2d' },\n },\n {\n binding: 4,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'non-filtering' },\n },\n ],\n };\n }\n case 'fullscreen-post-with-scene-depth-msaa': {\n return {\n label: 'fullscreen-post-with-scene-depth-msaa-bgl',\n entries: [\n ...buildFullscreenPostInputEntries(spec),\n {\n binding: 2,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n buffer: { type: 'uniform' },\n },\n {\n binding: 3,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType: 'depth', viewDimension: '2d', multisampled: true },\n },\n {\n binding: 4,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: { type: 'non-filtering' },\n },\n ],\n };\n }\n }\n}\n\n/**\n * The shared texture@0 + sampler@1 entries for fullscreen post-process BGLs.\n * sampleType is derived from `spec.attachments` (R3 fix): depth attachments →\n * `'depth'` + `'comparison'` sampler; `'r32float'` → `'unfilterable-float'`;\n * else → `'float'` + `'filtering'`. Both `'fullscreen-post'` and\n * `'fullscreen-post-with-params'` reuse this so the derivation is one SSOT.\n */\nfunction buildFullscreenPostInputEntries(spec: PipelineSpec): GPUBindGroupLayoutEntry[] {\n const inputFormat: GPUTextureFormat | undefined =\n spec.attachments.depthFormat ?? spec.attachments.colorFormats[0];\n const sampleType: GPUTextureSampleType =\n inputFormat === 'depth32float' ||\n inputFormat === 'depth24plus' ||\n inputFormat === 'depth24plus-stencil8' ||\n inputFormat === 'depth16unorm'\n ? 'depth'\n : inputFormat === 'r32float'\n ? 'unfilterable-float'\n : 'float';\n return [\n {\n binding: 0,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n texture: { sampleType, viewDimension: '2d' },\n },\n {\n binding: 1,\n visibility: GPU_SHADER_STAGE_FRAGMENT,\n sampler: {\n type: sampleType === 'depth' ? 'comparison' : 'filtering',\n },\n },\n ];\n}\n\n// ══════════════════════════════════════════════════════════════════════════════\n","export const PROBE_BLEND_RECORD_BYTE_SIZE = 160;\n/** Dynamic-offset stride; 160B payload plus WebGPU's 256B alignment. */\nexport const PROBE_BLEND_RECORD_STRIDE = 256;\nexport const PROBE_BLEND_RECORD_FLOAT_COUNT =\n PROBE_BLEND_RECORD_BYTE_SIZE / Float32Array.BYTES_PER_ELEMENT;\nexport const PROBE_BLEND_RECORD_CAPACITY = 64;\nexport const PROBE_BLEND_SENTINEL = -1;\n\nexport type ProbeBlendRecordSentinel =\n | 'capacity-exceeded'\n | 'no-active'\n | 'no-lkg'\n | 'outside-radius';\n\nexport interface ProbeBlendRecord {\n readonly objectKey: number;\n readonly generation: number;\n readonly localBlendFraction: number;\n readonly shPreblend: readonly number[];\n readonly bytes: Uint8Array;\n readonly byteLength: number;\n readonly candidate: boolean;\n readonly accepted: boolean;\n readonly lastKnownGood: boolean;\n readonly sentinel?: ProbeBlendRecordSentinel;\n}\n\nexport function emptyProbeBlendRecord(\n objectKey = PROBE_BLEND_SENTINEL,\n sentinel: ProbeBlendRecordSentinel = 'no-lkg',\n): ProbeBlendRecord {\n const bytes = new Uint8Array(PROBE_BLEND_RECORD_BYTE_SIZE);\n return {\n objectKey,\n generation: 0,\n localBlendFraction: 0,\n shPreblend: new Array<number>(27).fill(0),\n bytes,\n byteLength: bytes.byteLength,\n candidate: false,\n accepted: false,\n lastKnownGood: false,\n sentinel,\n };\n}\n\nexport function probeBlendRecordOffset(objectKey: number): number {\n if (!Number.isInteger(objectKey) || objectKey < 0) {\n throw new Error('probe blend record requires a non-negative object key');\n }\n // Lane zero is reserved for the no-LKG sentinel. RenderScene slot identity\n // is the object index, so objectKey N always selects lane N+1.\n return (objectKey + 1) * PROBE_BLEND_RECORD_STRIDE;\n}\n","import type { TextureView } from '@forgeax/engine-rhi';\nimport type { RenderError } from '../errors/render';\nimport {\n RenderTargetDescriptorInvalidError,\n RenderTargetStateInvalidError,\n} from '../errors/render';\nimport type { RenderResult } from '../render-contract';\nimport type {\n RenderTarget,\n RenderTargetDescriptor,\n RenderTargetTextureSource,\n RenderTargetTextureSourceOptions,\n} from './contracts';\n\nexport interface RenderTargetMaterialSourceView {\n readonly dimension: RenderTargetTextureSourceOptions['dimension'];\n readonly mipLevel: number;\n readonly resolveRequired: boolean;\n}\n\nexport interface RenderTargetMaterialSourceBinding {\n readonly source: RenderTargetTextureSource;\n readonly target: RenderTarget;\n readonly generation: number;\n readonly shape: RenderTargetDescriptor['shape'];\n readonly format: RenderTargetDescriptor['format'];\n readonly view: RenderTargetMaterialSourceView;\n /** Renderer-local physical view, present only for the active generation. */\n readonly textureView?: TextureView;\n}\n\nexport interface RenderTargetMaterialSourceExpectation {\n readonly target: RenderTarget;\n readonly generation: number;\n readonly shape: RenderTargetDescriptor['shape'];\n readonly format: RenderTargetDescriptor['format'];\n readonly dimension: RenderTargetTextureSourceOptions['dimension'];\n readonly mipLevel: number;\n}\n\nconst sourceBindings = new WeakMap<object, RenderTargetMaterialSourceBinding>();\nconst targetIdentities = new WeakMap<object, number>();\nlet nextTargetIdentity = 1;\n\nfunction targetIdentity(target: RenderTarget): number {\n const object = target as object;\n const existing = targetIdentities.get(object);\n if (existing !== undefined) return existing;\n const identity = nextTargetIdentity;\n nextTargetIdentity += 1;\n targetIdentities.set(object, identity);\n return identity;\n}\n\nfunction sourceToken(): RenderTargetTextureSource {\n return Object.freeze({}) as RenderTargetTextureSource;\n}\n\n/** Resolve a source only inside the renderer-owned material projection. */\nexport function resolveRenderTargetMaterialSource(\n source: RenderTargetTextureSource,\n): RenderTargetMaterialSourceBinding | undefined {\n return sourceBindings.get(source as object);\n}\n\n/**\n * Returns the stable renderer-local resource identity used by batch grouping.\n * The opaque source object is intentionally not stringified: target identity,\n * device generation, and view subresource are the producer-owned facts that\n * determine whether two draws may share one material bind group.\n */\nexport function renderTargetMaterialSourceIdentity(\n source: RenderTargetTextureSource,\n): string | undefined {\n const binding = resolveRenderTargetMaterialSource(source);\n if (binding === undefined) return undefined;\n return [\n targetIdentity(binding.target),\n binding.generation,\n binding.shape,\n binding.format,\n binding.view.dimension,\n binding.view.mipLevel,\n binding.view.resolveRequired ? 1 : 0,\n ].join(':');\n}\n\nfunction invalid(\n field: string,\n value: unknown,\n expected: string,\n): RenderResult<never, RenderError> {\n return {\n ok: false,\n error: new RenderTargetDescriptorInvalidError({ field, value, expected }),\n };\n}\n\nexport function createRenderTargetMaterialSource(\n target: RenderTarget,\n descriptor: RenderTargetDescriptor,\n options: RenderTargetTextureSourceOptions & { readonly generation: number },\n): RenderResult<RenderTargetMaterialSourceBinding, RenderError> {\n if (options.aspect !== 'color') return invalid('aspect', options.aspect, 'color');\n if (options.dimension !== descriptor.shape) {\n return invalid('dimension', options.dimension, `dimension matches ${descriptor.shape}`);\n }\n const mipCount =\n descriptor.mipLevels === 1\n ? 1\n : Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;\n if (!Number.isInteger(options.mipLevel) || options.mipLevel < 0 || options.mipLevel >= mipCount) {\n return invalid('mipLevel', options.mipLevel, `an admitted mip level below ${mipCount}`);\n }\n if (!Number.isInteger(options.generation) || options.generation < 0) {\n return invalid('generation', options.generation, 'a non-negative device generation');\n }\n const result: RenderResult<RenderTargetMaterialSourceBinding, RenderError> = {\n ok: true,\n value: Object.freeze({\n source: sourceToken(),\n target,\n generation: options.generation,\n shape: descriptor.shape,\n format: descriptor.format,\n view: Object.freeze({\n dimension: options.dimension,\n mipLevel: options.mipLevel,\n resolveRequired: descriptor.sampleCount === 4,\n }),\n }),\n };\n sourceBindings.set(result.value.source as object, result.value);\n return result;\n}\n\nexport function validateRenderTargetMaterialSource(\n binding: RenderTargetMaterialSourceBinding,\n expected: RenderTargetMaterialSourceExpectation,\n): RenderResult<void, RenderError> {\n if (binding.target !== expected.target) {\n return {\n ok: false,\n error: new RenderTargetStateInvalidError({\n operation: 'source',\n reason: 'foreign-renderer',\n state: 'active',\n generation: binding.generation,\n }),\n };\n }\n if (binding.generation !== expected.generation) {\n return {\n ok: false,\n error: new RenderTargetStateInvalidError({\n operation: 'source',\n reason: 'generation-mismatch',\n state: 'active',\n generation: binding.generation,\n }),\n };\n }\n if (binding.shape !== expected.shape || binding.format !== expected.format) {\n return invalid(\n 'descriptor',\n { shape: binding.shape, format: binding.format },\n 'matching target descriptor',\n );\n }\n if (\n binding.view.dimension !== expected.dimension ||\n binding.view.mipLevel !== expected.mipLevel\n ) {\n return invalid('view', binding.view, 'matching target view subresource');\n }\n return { ok: true, value: undefined };\n}\n","// M3 / w19: PassSelector matching logic\n// (feat-20260526-material-asset-multipass-renderstate)\n//\n// Pure-function helpers for matching MaterialPass tags against\n// a PassSelector. Plan-strategy D-4: Tags free Record + PassSelector\n// Record<string, string[]>. Requirements AC-05.\n\nimport type { MaterialPass, PassSelector } from '@forgeax/engine-types';\n\n/**\n * Test whether a pass's tags match a {@link PassSelector}.\n *\n * Matching rule (AC-05): every key in the selector must exist in the pass's\n * `tags` and the pass's tag value must be in the selector's value list for\n * that key. An empty selector matches every pass.\n *\n * @param tags The pass-level tags (free key-value pairs)\n * @param selector The selector to match against\n */\nexport function matchPass(tags: Record<string, string>, selector: PassSelector): boolean {\n if (Object.keys(selector).length === 0) return true;\n for (const [key, allowedValues] of Object.entries(selector)) {\n const passValue = tags[key];\n if (passValue === undefined) return false;\n if ((allowedValues as readonly string[]).length === 0) return false;\n if (!(allowedValues as readonly string[]).includes(passValue)) return false;\n }\n return true;\n}\n\n/**\n * Filter passes whose tags match the given {@link PassSelector}.\n *\n * An empty selector matches all passes (returns the input array reference).\n * Otherwise each pass is checked via {@link matchPass}.\n *\n * @param passes The material's pass descriptors\n * @param selector The pass selector\n * @returns Filtered array of matching passes\n */\nexport function selectPasses(\n passes: readonly MaterialPass[],\n selector: PassSelector,\n): readonly MaterialPass[] {\n if (Object.keys(selector).length === 0) return passes;\n return passes.filter((p) =>\n matchPass((p.renderState?.tags as Record<string, string> | undefined) ?? {}, selector),\n );\n}\n","import type {\n MaterialShaderArtifact,\n MaterialShaderArtifactReceipt,\n MaterialShaderVertexInput,\n} from '@forgeax/engine-shader';\nimport type { PrimitiveTopology } from '@forgeax/engine-types';\nimport {\n GpuDrivenPreparationError,\n type GpuDrivenPreparationErrorDetail,\n} from '../errors/gpu-driven';\nimport type { RenderableSnapshot } from '../render-system-extract';\n\nexport interface GpuDrivenGeometryReceipt {\n readonly identity: string;\n readonly vertexInputs: readonly MaterialShaderVertexInput[];\n readonly topology: PrimitiveTopology;\n readonly indexed: boolean;\n}\n\nexport interface GpuDrivenSkinReceipt {\n readonly identity: string;\n readonly generation: number;\n readonly group: number;\n readonly binding: number;\n readonly byteOffset: number;\n}\n\nexport interface PreparedGpuDrivenDraw {\n readonly identity: {\n readonly material: string;\n readonly geometry: string;\n readonly deformation: 'rigid' | 'skin';\n };\n readonly receiptGeneration: number;\n /** Content/layout identity that separates ABI variants (for example COLOR_0). */\n readonly receiptIdentity?: string;\n readonly directEntry: string;\n readonly sceneIndexEntry: string;\n readonly materialRow: MaterialShaderArtifactReceipt['materialRow'];\n readonly resourceSlots: MaterialShaderArtifactReceipt['resourceSlots'];\n readonly uvSets: MaterialShaderArtifactReceipt['uvSets'];\n readonly vertexInputs: MaterialShaderArtifactReceipt['vertexInputs'];\n readonly alphaMask: MaterialShaderArtifactReceipt['alphaMask'];\n readonly skinPaletteAddress: MaterialShaderArtifactReceipt['skinPaletteAddress'];\n readonly topology: PrimitiveTopology;\n readonly indexed: boolean;\n readonly first: number;\n readonly count: number;\n readonly baseVertex: number;\n}\n\n/** Exact extracted draw range consumed by the preparation owner. */\nexport interface GpuDrivenDrawRange {\n readonly kind: 'indexed' | 'non-indexed';\n readonly first: number;\n readonly count: number;\n readonly baseVertex: number;\n readonly topology: PrimitiveTopology;\n}\n\nexport interface PrepareGpuDrivenDrawInput {\n readonly snapshot: RenderableSnapshot;\n readonly artifact: MaterialShaderArtifact;\n readonly geometry: GpuDrivenGeometryReceipt;\n readonly generation: number;\n /** The submesh draw currently being prepared; never infer draw zero. */\n readonly draw: GpuDrivenDrawRange;\n readonly skinReceipt?: GpuDrivenSkinReceipt;\n}\n\nfunction failure(\n code: ConstructorParameters<typeof GpuDrivenPreparationError>[0],\n detail: GpuDrivenPreparationErrorDetail,\n): { readonly ok: false; readonly error: GpuDrivenPreparationError } {\n return { ok: false, error: new GpuDrivenPreparationError(code, detail) };\n}\n\nfunction sameVertexInputs(\n expected: readonly MaterialShaderVertexInput[],\n actual: readonly MaterialShaderVertexInput[],\n): boolean {\n return (\n expected.length === actual.length &&\n expected.every(\n (input, index) =>\n input.semantic === actual[index]?.semantic &&\n input.location === actual[index]?.location &&\n input.format === actual[index]?.format,\n )\n );\n}\n\nfunction hasMaterialResources(\n snapshot: RenderableSnapshot,\n receipt: MaterialShaderArtifactReceipt,\n) {\n // Video frames and renderer-local target sources have no stable\n // scene-index binding in this feature. Extract keeps those draws on the\n // explicit CPU semantic lane; direct contract callers must fail closed too.\n if (\n (snapshot.material.textureSources?.size ?? 0) > 0 ||\n (snapshot.material.videoTextureFields?.size ?? 0) > 0\n ) {\n return false;\n }\n const textures = snapshot.material.textureHandles;\n const samplers = snapshot.material.samplerHandles;\n const authoredTextures = snapshot.material.authoredTextureFields;\n const authoredSamplers = snapshot.material.authoredSamplerFields;\n // Standard PBR declares optional texture slots whose missing values are\n // supplied by the existing frame material producer (white, flat-normal,\n // black, or the configured IBL defaults). Only an explicitly authored slot\n // is a readiness requirement; this keeps numeric-only PBR on the same GPU\n // lane while still rejecting an authored handle that failed to resolve.\n return receipt.resourceSlots.every((slot) => {\n // Storage-buffer resources have no MaterialSnapshot handle surface yet;\n // admitting them as samplers would silently turn an authored resource\n // failure into a prepared draw with an unrelated binding.\n if (slot.kind === 'storage-buffer') return false;\n if (slot.kind === 'texture') {\n if (!authoredTextures?.has(slot.parameter)) return true;\n return (\n textures?.has(slot.parameter) === true ||\n snapshot.material.textureSources?.has(slot.parameter) === true ||\n snapshot.material.videoTextureFields?.has(slot.parameter) === true\n );\n }\n if (!authoredSamplers?.has(slot.parameter)) return true;\n return samplers?.has(slot.parameter) === true;\n });\n}\n\nexport function prepareGpuDrivenDraw(\n input: PrepareGpuDrivenDrawInput,\n):\n | { readonly ok: true; readonly value: PreparedGpuDrivenDraw }\n | { readonly ok: false; readonly error: GpuDrivenPreparationError } {\n const receipt = input.artifact.receipt;\n if (receipt === undefined) {\n return failure('missing-material-receipt', {\n reason: 'material-receipt-missing',\n owner: 'material',\n expected: 'MaterialShaderArtifact.receipt',\n });\n }\n if (receipt.generation !== input.generation) {\n return failure('stale-generation', {\n reason: 'generation-stale',\n owner: 'generation',\n expectedGeneration: input.generation,\n actualGeneration: receipt.generation,\n });\n }\n if (receipt.reflection.layoutIdentity !== input.artifact.layoutIdentity) {\n return failure('reflection-mismatch', {\n reason: 'reflection-receipt-mismatch',\n owner: 'material',\n expected: input.artifact.layoutIdentity,\n actual: receipt.reflection.layoutIdentity,\n });\n }\n if (receipt.uvSets.some((uv) => uv.set > 0) && input.geometry.vertexInputs.length < 3) {\n return failure('missing-uv', {\n reason: 'uv-set-missing',\n owner: 'geometry',\n expected: `${receipt.uvSets.length} material UV sets`,\n actual: `${input.geometry.vertexInputs.filter((vertex) => vertex.semantic.startsWith('uv')).length} geometry UV sets`,\n });\n }\n if (!sameVertexInputs(receipt.vertexInputs, input.geometry.vertexInputs)) {\n return failure('vertex-input-mismatch', {\n reason: 'vertex-semantic-mismatch',\n owner: 'geometry',\n expected: receipt.vertexInputs.map((input) => input.semantic).join(','),\n actual: input.geometry.vertexInputs.map((input) => input.semantic).join(','),\n });\n }\n const hasAlphaMask = receipt.alphaMask.cutoff.length > 0 || receipt.alphaMask.source.length > 0;\n if (\n hasAlphaMask &&\n (receipt.alphaMask.cutoff.length === 0 || receipt.alphaMask.source.length === 0)\n ) {\n return failure('alpha-mask-mismatch', {\n reason: 'alpha-mask-receipt-missing',\n owner: 'material',\n expected: 'alphaMask.cutoff and alphaMask.source for a masked Pass',\n });\n }\n if (!hasMaterialResources(input.snapshot, receipt)) {\n return failure('resource-not-ready', {\n reason: 'material-resource-missing',\n owner: 'material',\n expected: receipt.resourceSlots.map((slot) => slot.parameter).join(','),\n });\n }\n const deformation = input.snapshot.skin === undefined ? 'rigid' : 'skin';\n if (deformation === 'skin') {\n if (input.skinReceipt === undefined || receipt.skinPaletteAddress === undefined) {\n return failure('skin-receipt-mismatch', {\n reason: 'skin-address-missing',\n owner: 'skin',\n expected: 'skinPaletteAddress and skinReceipt',\n });\n }\n if (\n input.skinReceipt.identity !== input.snapshot.skin?.identity ||\n input.skinReceipt.generation !== input.snapshot.skin?.generation ||\n input.skinReceipt.group !== receipt.skinPaletteAddress.group ||\n input.skinReceipt.binding !== receipt.skinPaletteAddress.binding\n ) {\n return failure('skin-receipt-mismatch', {\n reason: 'skin-address-missing',\n owner: 'skin',\n expected: `${receipt.skinPaletteAddress.group}:${receipt.skinPaletteAddress.binding}@${input.snapshot.skin?.generation ?? '<missing>'}`,\n actual: `${input.skinReceipt.group}:${input.skinReceipt.binding}@${input.skinReceipt.generation}`,\n });\n }\n }\n return {\n ok: true,\n value: {\n identity: {\n material: input.artifact.material,\n geometry: input.geometry.identity,\n deformation,\n },\n receiptGeneration: receipt.generation,\n receiptIdentity: receipt.receiptIdentity,\n directEntry: receipt.directEntry,\n sceneIndexEntry: receipt.sceneIndexEntry,\n materialRow: receipt.materialRow,\n resourceSlots: receipt.resourceSlots,\n uvSets: receipt.uvSets,\n vertexInputs: receipt.vertexInputs,\n alphaMask: receipt.alphaMask,\n skinPaletteAddress: receipt.skinPaletteAddress,\n topology: input.draw.topology,\n indexed: input.draw.kind === 'indexed',\n first: input.draw.first,\n count: input.draw.count,\n baseVertex: input.draw.baseVertex,\n },\n };\n}\n","import { deriveVertexLayoutProjection } from '@forgeax/engine-geometry';\nimport type { MaterialShaderArtifact } from '@forgeax/engine-shader';\nimport type { MeshAsset } from '@forgeax/engine-types';\nimport { GpuDrivenPreparationError } from '../errors/gpu-driven';\nimport {\n type GpuDrivenDrawRange,\n type GpuDrivenGeometryReceipt,\n type GpuDrivenSkinReceipt,\n type PreparedGpuDrivenDraw,\n type PrepareGpuDrivenDrawInput,\n prepareGpuDrivenDraw,\n} from '../gpu-driven/prepared-draw';\nimport { isCanonicalStandardPbrMaterialShader } from '../pbr-pipeline';\nimport type { MaterialSnapshot, RenderableSnapshot } from '../render-system-extract';\n\nexport {\n GpuDrivenPreparationError,\n type GpuDrivenPreparationErrorCode,\n type GpuDrivenPreparationErrorDetail,\n type GpuDrivenPreparationReason,\n} from '../errors/gpu-driven';\nexport {\n type GpuDrivenDrawRange,\n type GpuDrivenGeometryReceipt,\n type GpuDrivenSkinReceipt,\n type PreparedGpuDrivenDraw,\n type PrepareGpuDrivenDrawInput,\n prepareGpuDrivenDraw,\n} from '../gpu-driven/prepared-draw';\n\nexport interface GpuDrivenDrawSnapshot {\n /** Stable source submesh identity; compact draw arrays must not renumber it. */\n readonly drawItemIndex?: number;\n readonly kind: GpuDrivenDrawRange['kind'];\n readonly first: GpuDrivenDrawRange['first'];\n readonly count: GpuDrivenDrawRange['count'];\n readonly baseVertex: GpuDrivenDrawRange['baseVertex'];\n readonly materialSlot: number;\n readonly topology: GpuDrivenDrawRange['topology'];\n readonly pipelineClass: string;\n readonly materialResourceClass: string;\n /** Producer-owned prepared ABI facts used by the PBR GPU lane. */\n readonly prepared?: PreparedGpuDrivenDraw;\n /** Structured producer failure; record never interprets an incomplete draw. */\n readonly preparationError?: GpuDrivenPreparationError;\n /** Optional lower-detail ranges aligned with the snapshot's LOD levels. */\n readonly lodRanges?: readonly {\n readonly first: number;\n readonly count: number;\n readonly baseVertex: number;\n }[];\n /** Optional camera-projected height supplied by direct GPU-view evidence. */\n readonly projectedHeight?: number;\n}\n\n/** Stable ownership key for one entity/material/concrete GPU draw item. */\nexport function gpuDrivenDrawKey(\n worldEntity: number,\n materialHandle: number,\n drawItemIndex: number,\n): string {\n return `${worldEntity}:${materialHandle}:${drawItemIndex}`;\n}\n\n/** Stable ShadowCaster ownership key: entity, concrete GPU draw item, and pass. */\nexport function gpuDrivenShadowDrawKey(\n worldEntity: number,\n materialHandle: number,\n drawItemIndex: number,\n passIndex: number,\n): string {\n return `${gpuDrivenDrawKey(worldEntity, materialHandle, drawItemIndex)}:${passIndex}`;\n}\n\n/**\n * Stable lookup key for the producer-published material artifact selected by\n * one prepared draw. The receipt identity is intentionally part of the key:\n * a COLOR_0 variant (or any later ABI variant) must never share a pipeline or\n * projection cache entry with its no-color sibling.\n */\nexport function gpuDrivenMaterialArtifactKey(input: {\n readonly material: string;\n readonly deformation: 'rigid' | 'skin';\n readonly receiptIdentity: string | undefined;\n readonly receiptGeneration: number;\n}): string {\n return [\n input.material,\n input.deformation,\n input.receiptIdentity ?? '<legacy-receipt>',\n input.receiptGeneration,\n ].join('|');\n}\n\n/** Resolve the producer-owned source identity for one compact draw snapshot. */\nexport function gpuDrivenSourceDrawItemIndex(\n draw: GpuDrivenDrawSnapshot,\n compactIndex: number,\n): number {\n return draw.drawItemIndex ?? compactIndex;\n}\n\n/**\n * Resolves prepared facts once at extract time; record never re-reads assets.\n * The resolver surfaces UV, reflection, vertex, alpha, resource, and\n * generation failures as GpuDrivenPreparationError before recording.\n */\nexport function resolvePreparedGpuDrivenDraw(input: PrepareGpuDrivenDrawInput):\n | { readonly ok: true; readonly value: PreparedGpuDrivenDraw }\n | {\n readonly ok: false;\n readonly error: import('../errors/gpu-driven').GpuDrivenPreparationError;\n } {\n return prepareGpuDrivenDraw(input);\n}\n\n/** Keeps the artifact type visible at this owner boundary for contract checks. */\nexport type PreparedGpuDrivenArtifact = MaterialShaderArtifact;\n\n/**\n * Derives the resource identity consumed by the existing GPU-driven batch\n * owner. The extract stage is the only place that resolves material values;\n * this helper keeps the batch adapter from re-reading assets later.\n */\nexport function gpuDrivenMaterialResourceClass(material: MaterialSnapshot): string {\n const textures = [...(material.textureHandles?.entries() ?? [])]\n .map(([name, handle]) => [name, Number(handle)] as const)\n .sort(([left], [right]) => left.localeCompare(right));\n const samplers = [...(material.samplerHandles?.entries() ?? [])]\n .map(([name, handle]) => [name, Number(handle)] as const)\n .sort(([left], [right]) => left.localeCompare(right));\n return JSON.stringify({\n textures,\n samplers,\n });\n}\n\n/**\n * Dynamic renderer-local targets and video frames are owned by their host\n * producers and do not have a stable scene-index binding in this feature.\n * Keep them on the explicit CPU semantic lane instead of inventing a\n * per-instance resource table or grouping opaque source objects by shape.\n */\nfunction hasCpuOnlyMaterialResources(material: MaterialSnapshot): boolean {\n return (material.textureSources?.size ?? 0) > 0 || (material.videoTextureFields?.size ?? 0) > 0;\n}\n\n/**\n * Projects already-resolved mesh facts into the existing GPU-driven draw\n * snapshot. No World or AssetRegistry access is permitted at this boundary.\n */\ninterface BuildGpuDrivenDrawsInput {\n readonly mesh: MeshAsset | undefined;\n readonly materials: readonly MaterialSnapshot[];\n readonly fallbackMaterial: MaterialSnapshot;\n readonly baseSnapshot: RenderableSnapshot;\n readonly getMaterialShaderArtifact?: (\n materialShaderId: string,\n request?: {\n readonly vertexColorAvailable?: boolean;\n readonly deformation?: 'rigid' | 'skin';\n readonly pass?: 'forward' | 'shadow' | 'depth';\n readonly address?: 'direct' | 'scene-index';\n },\n ) => MaterialShaderArtifact | undefined;\n /** Resolved lower-detail meshes, in the same order as baseSnapshot.lods. */\n readonly lodMeshes?: readonly (MeshAsset | undefined)[];\n}\n\ninterface LegacyBuildGpuDrivenDrawsInput {\n readonly submeshes: readonly MeshAsset['submeshes'][number][];\n readonly indexed: boolean;\n readonly materials: readonly MaterialSnapshot[];\n readonly fallbackMaterial: MaterialSnapshot;\n readonly prepare?: (\n draw: GpuDrivenDrawSnapshot,\n material: MaterialSnapshot,\n ) => PreparedGpuDrivenDraw | undefined;\n}\n\nexport function buildGpuDrivenDraws(input: BuildGpuDrivenDrawsInput): GpuDrivenDrawSnapshot[];\nexport function buildGpuDrivenDraws(input: LegacyBuildGpuDrivenDrawsInput): GpuDrivenDrawSnapshot[];\nexport function buildGpuDrivenDraws(\n input: BuildGpuDrivenDrawsInput | LegacyBuildGpuDrivenDrawsInput,\n): GpuDrivenDrawSnapshot[] {\n const legacy = 'submeshes' in input;\n if (!legacy && input.mesh === undefined) return [];\n const parsedMesh = legacy ? undefined : input.mesh;\n if (!legacy && parsedMesh === undefined) return [];\n const indexed = legacy ? input.indexed : parsedMesh?.indices !== undefined;\n const submeshes = legacy ? input.submeshes : (parsedMesh?.submeshes ?? []);\n const layoutProjection =\n parsedMesh === undefined ? undefined : deriveVertexLayoutProjection(parsedMesh.attributes);\n const geometry: GpuDrivenGeometryReceipt = {\n identity:\n parsedMesh === undefined\n ? '<no-mesh>'\n : `${(parsedMesh as { guid?: string }).guid ?? '<no-guid>'}:${layoutProjection?.digest ?? ''}`,\n vertexInputs: (layoutProjection?.attributes ?? []).map((attribute) => ({\n semantic: attribute.key,\n location: attribute.shaderLocation,\n format: attribute.format,\n })),\n topology: submeshes[0]?.topology ?? 'triangle-list',\n indexed,\n };\n let nonIndexedFirst = 0;\n return submeshes.flatMap((submesh, drawItemIndex) => {\n const drawMaterial = input.materials[submesh.materialSlot] ?? input.fallbackMaterial;\n const first = indexed ? submesh.indexOffset : nonIndexedFirst;\n nonIndexedFirst += submesh.vertexCount;\n if (drawMaterial.transparent === true) return [];\n const draw: GpuDrivenDrawSnapshot = {\n drawItemIndex,\n kind: indexed ? ('indexed' as const) : ('non-indexed' as const),\n first,\n count: indexed ? submesh.indexCount : submesh.vertexCount,\n baseVertex: 0,\n materialSlot: submesh.materialSlot,\n topology: submesh.topology,\n pipelineClass: `${drawMaterial.materialShaderId ?? 'forgeax::default-unlit'}|${submesh.topology}|${JSON.stringify(drawMaterial.renderState ?? null)}`,\n materialResourceClass: gpuDrivenMaterialResourceClass(drawMaterial),\n };\n const lodRanges = !legacy\n ? input.lodMeshes?.map((lodMesh) => {\n if (lodMesh === undefined) return undefined;\n const lower = lodMesh.submeshes[drawItemIndex];\n if (lower === undefined) return undefined;\n const lowerIndexed = lodMesh.indices !== undefined;\n const lowerFirst = lowerIndexed\n ? lower.indexOffset\n : lodMesh.submeshes\n .slice(0, drawItemIndex)\n .reduce((offset, entry) => offset + entry.vertexCount, 0);\n return {\n first: lowerFirst,\n count: lowerIndexed ? lower.indexCount : lower.vertexCount,\n baseVertex: 0,\n };\n })\n : undefined;\n const withLodRanges =\n lodRanges?.length !== 0 && lodRanges?.every((range) => range !== undefined)\n ? { lodRanges: lodRanges as { first: number; count: number; baseVertex: number }[] }\n : {};\n const prepared = legacy\n ? input.prepare?.(draw, drawMaterial)\n : hasCpuOnlyMaterialResources(drawMaterial)\n ? undefined\n : (() => {\n const materialShaderId = drawMaterial.materialShaderId;\n const vertexColorAvailable = geometry.vertexInputs.some(\n (input) => input.semantic === 'color',\n );\n // The snapshot keeps the direct program key as its logical\n // material identity. A published scene-index program has a\n // separate specialization key; resolve that concrete artifact\n // before preparing the draw so the indirect pipeline receives the\n // scene entry rather than silently reusing the direct shader.\n const sceneIndexProgramKey = Object.entries(\n drawMaterial.materialSceneIndexProgramKeys ?? {},\n ).find(\n ([passName, program]) =>\n program.pass === 'forward' &&\n drawMaterial.materialProgramKeys?.[passName] === materialShaderId,\n )?.[1]?.specializationKey;\n const artifact =\n materialShaderId === undefined\n ? undefined\n : input.getMaterialShaderArtifact?.(sceneIndexProgramKey ?? materialShaderId, {\n vertexColorAvailable,\n deformation: input.baseSnapshot.skin === undefined ? 'rigid' : 'skin',\n pass: 'forward',\n address: 'scene-index',\n });\n // Canonical roots and explicitly published scene-index programs\n // require their producer receipt. Legacy direct-only aliases do not.\n const requiresReceipt =\n isCanonicalStandardPbrMaterialShader(materialShaderId) ||\n sceneIndexProgramKey !== undefined;\n\n if (artifact === undefined) {\n return input.getMaterialShaderArtifact !== undefined && requiresReceipt\n ? new GpuDrivenPreparationError('missing-material-receipt', {\n reason: 'material-receipt-missing',\n owner: 'material',\n expected: `artifact for ${materialShaderId}`,\n })\n : undefined;\n }\n const receipt = artifact.receipt;\n if (receipt === undefined) {\n return new GpuDrivenPreparationError('missing-material-receipt', {\n reason: 'material-receipt-missing',\n owner: 'material',\n expected: `receipt for ${materialShaderId}`,\n });\n }\n const skinReceipt: GpuDrivenSkinReceipt | undefined =\n input.baseSnapshot.skin !== undefined && receipt.skinPaletteAddress !== undefined\n ? {\n identity: input.baseSnapshot.skin.identity,\n generation: input.baseSnapshot.skin.generation,\n group: receipt.skinPaletteAddress.group,\n binding: receipt.skinPaletteAddress.binding,\n byteOffset: input.baseSnapshot.skin.byteOffset,\n }\n : undefined;\n const selectedArtifact =\n artifact === undefined ||\n sceneIndexProgramKey === undefined ||\n materialShaderId === undefined\n ? artifact\n : {\n ...artifact,\n material: materialShaderId,\n specializationKey: sceneIndexProgramKey,\n };\n const result = resolvePreparedGpuDrivenDraw({\n snapshot: { ...input.baseSnapshot, material: drawMaterial },\n artifact: selectedArtifact ?? artifact,\n geometry: { ...geometry, topology: draw.topology, indexed: draw.kind === 'indexed' },\n generation: receipt.generation,\n draw,\n ...(skinReceipt === undefined ? {} : { skinReceipt }),\n });\n return result.ok ? result.value : result.error;\n })();\n if (prepared instanceof GpuDrivenPreparationError) {\n return [{ ...draw, preparationError: prepared, ...withLodRanges }];\n }\n return [\n prepared === undefined\n ? { ...draw, ...withLodRanges }\n : { ...draw, prepared, ...withLodRanges },\n ];\n });\n}\n"]}