@forgeax/engine-render 0.1.21 → 0.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (584) hide show
  1. package/README.md +281 -38
  2. package/dist/assembly/backend-contract.d.ts +13 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/bundler-contract.d.ts +9 -0
  5. package/dist/assembly/bundler-contract.d.ts.map +1 -0
  6. package/dist/assembly/device-feature-admission.d.ts +8 -0
  7. package/dist/assembly/device-feature-admission.d.ts.map +1 -1
  8. package/dist/assembly/extended-lighting-fallback.d.ts +13 -0
  9. package/dist/assembly/extended-lighting-fallback.d.ts.map +1 -0
  10. package/dist/assembly/factory.d.ts +7 -235
  11. package/dist/assembly/factory.d.ts.map +1 -1
  12. package/dist/assembly/host-contract.d.ts +10 -0
  13. package/dist/assembly/host-contract.d.ts.map +1 -1
  14. package/dist/assembly/material/assembly.d.ts +3 -2
  15. package/dist/assembly/material/assembly.d.ts.map +1 -1
  16. package/dist/assembly/material/standard-layer-projection.d.ts +10 -0
  17. package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -0
  18. package/dist/assembly/material-shader-policy.d.ts +168 -0
  19. package/dist/assembly/material-shader-policy.d.ts.map +1 -0
  20. package/dist/assembly/material-shader-prewarm.d.ts +21 -0
  21. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -0
  22. package/dist/assembly/mesh-ssbo-grow.d.ts +88 -0
  23. package/dist/assembly/mesh-ssbo-grow.d.ts.map +1 -0
  24. package/dist/assembly/recovery/device-loss-fanout.d.ts +14 -0
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -0
  26. package/dist/assembly/recovery/generation.d.ts +46 -0
  27. package/dist/assembly/recovery/generation.d.ts.map +1 -0
  28. package/dist/assembly/recovery/recovery-attempt.d.ts +63 -0
  29. package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -0
  30. package/dist/assembly/recovery/renderer-recover.d.ts +115 -0
  31. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -0
  32. package/dist/assembly/renderer-facade.d.ts +10 -0
  33. package/dist/assembly/renderer-facade.d.ts.map +1 -0
  34. package/dist/assembly/renderer-frame-transaction.d.ts +17 -0
  35. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  36. package/dist/assembly/renderer-helpers.d.ts +19 -0
  37. package/dist/assembly/renderer-helpers.d.ts.map +1 -0
  38. package/dist/assembly/renderer-lifecycle.d.ts +34 -0
  39. package/dist/assembly/renderer-lifecycle.d.ts.map +1 -1
  40. package/dist/assembly/shader-prewarm-policy.d.ts +15 -0
  41. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -0
  42. package/dist/assembly/webgpu-ready-contract.d.ts +9 -0
  43. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -0
  44. package/dist/assembly/webgpu-ready.d.ts +55 -0
  45. package/dist/assembly/webgpu-ready.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-renderer.d.ts +152 -0
  47. package/dist/assembly/webgpu-renderer.d.ts.map +1 -0
  48. package/dist/authoring.mjs +1 -1
  49. package/dist/{chunk-PCHBPYML.mjs → chunk-GE3SDD72.mjs} +37 -5
  50. package/dist/chunk-GE3SDD72.mjs.map +1 -0
  51. package/dist/chunk-KZFTK6DO.mjs +1191 -0
  52. package/dist/chunk-KZFTK6DO.mjs.map +1 -0
  53. package/dist/{chunk-FS2KNUQH.mjs → chunk-Q752SHI5.mjs} +332 -568
  54. package/dist/chunk-Q752SHI5.mjs.map +1 -0
  55. package/dist/{chunk-6OPXDQ2E.mjs → chunk-RR5L4SRS.mjs} +33 -294
  56. package/dist/chunk-RR5L4SRS.mjs.map +1 -0
  57. package/dist/chunk-TFH5I7JJ.mjs +296 -0
  58. package/dist/chunk-TFH5I7JJ.mjs.map +1 -0
  59. package/dist/chunk-UQYS7FRM.mjs +1003 -0
  60. package/dist/chunk-UQYS7FRM.mjs.map +1 -0
  61. package/dist/chunk-YKB5DQV7.mjs +345 -0
  62. package/dist/chunk-YKB5DQV7.mjs.map +1 -0
  63. package/dist/{chunk-5YADUCA7.mjs → chunk-YRUYGA4A.mjs} +1189 -1217
  64. package/dist/chunk-YRUYGA4A.mjs.map +1 -0
  65. package/dist/chunk-Z3YYH2MB.mjs +5082 -0
  66. package/dist/chunk-Z3YYH2MB.mjs.map +1 -0
  67. package/dist/cluster-binner.d.ts +5 -0
  68. package/dist/cluster-binner.d.ts.map +1 -1
  69. package/dist/components/index.d.ts +3 -0
  70. package/dist/components/index.d.ts.map +1 -1
  71. package/dist/components/light-helpers.d.ts +4 -0
  72. package/dist/components/light-helpers.d.ts.map +1 -1
  73. package/dist/components/light-probe.d.ts +9 -0
  74. package/dist/components/light-probe.d.ts.map +1 -0
  75. package/dist/components/rect-area-light.d.ts +12 -0
  76. package/dist/components/rect-area-light.d.ts.map +1 -0
  77. package/dist/components/scene-instance.d.ts +4 -0
  78. package/dist/components/scene-instance.d.ts.map +1 -1
  79. package/dist/components/spot-light.d.ts +3 -0
  80. package/dist/components/spot-light.d.ts.map +1 -1
  81. package/dist/construct-renderer.mjs +27276 -23232
  82. package/dist/construct-renderer.mjs.map +1 -1
  83. package/dist/device/device-scope.d.ts +2 -0
  84. package/dist/device/device-scope.d.ts.map +1 -1
  85. package/dist/device/gpu-residency.d.ts +32 -5
  86. package/dist/device/gpu-residency.d.ts.map +1 -1
  87. package/dist/device/lifecycle-transaction.d.ts +2 -0
  88. package/dist/device/lifecycle-transaction.d.ts.map +1 -0
  89. package/dist/environment/frame.d.ts +5 -0
  90. package/dist/environment/frame.d.ts.map +1 -1
  91. package/dist/environment/inspection.d.ts +7 -0
  92. package/dist/environment/inspection.d.ts.map +1 -1
  93. package/dist/environment/lifecycle.d.ts +20 -2
  94. package/dist/environment/lifecycle.d.ts.map +1 -1
  95. package/dist/errors/gpu-driven.d.ts +26 -0
  96. package/dist/errors/gpu-driven.d.ts.map +1 -0
  97. package/dist/errors/index.d.ts +1 -0
  98. package/dist/errors/index.d.ts.map +1 -1
  99. package/dist/errors/recover.d.ts +67 -3
  100. package/dist/errors/recover.d.ts.map +1 -1
  101. package/dist/errors/render.d.ts +39 -1
  102. package/dist/errors/render.d.ts.map +1 -1
  103. package/dist/extract/contracts.d.ts +899 -0
  104. package/dist/extract/contracts.d.ts.map +1 -0
  105. package/dist/extract/gpu-driven.d.ts +50 -0
  106. package/dist/extract/gpu-driven.d.ts.map +1 -0
  107. package/dist/extract/visibility.d.ts.map +1 -1
  108. package/dist/features/host.d.ts +2 -0
  109. package/dist/features/host.d.ts.map +1 -1
  110. package/dist/features/prepared-gpu-work.d.ts +3 -0
  111. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  112. package/dist/features/prepared-graphics-store.d.ts +2 -0
  113. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  114. package/dist/gpu-driven/batch-topology.d.ts +34 -0
  115. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  116. package/dist/gpu-driven/prepared-draw.d.ts +63 -0
  117. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
  118. package/dist/gpu-driven/production-raster.d.ts +126 -2
  119. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  120. package/dist/gpu-driven/view-gpu.d.ts +64 -1
  121. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  122. package/dist/gpu-scene-schema.d.ts +14 -0
  123. package/dist/gpu-scene-schema.d.ts.map +1 -1
  124. package/dist/gpu-scene.d.ts +9 -1
  125. package/dist/gpu-scene.d.ts.map +1 -1
  126. package/dist/gpu-usage.d.ts +0 -1
  127. package/dist/gpu-usage.d.ts.map +1 -1
  128. package/dist/hdrp-buffers.d.ts +3 -3
  129. package/dist/hdrp-buffers.d.ts.map +1 -1
  130. package/dist/ibl/IblPipelineCache.d.ts +7 -6
  131. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  132. package/dist/ibl/skylight-bind-group.d.ts +7 -1
  133. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  134. package/dist/index.d.ts +13 -2
  135. package/dist/index.d.ts.map +1 -1
  136. package/dist/index.mjs +90 -5
  137. package/dist/index.mjs.map +1 -1
  138. package/dist/inspection-types.d.ts +163 -1
  139. package/dist/inspection-types.d.ts.map +1 -1
  140. package/dist/internal.d.ts +9 -0
  141. package/dist/internal.d.ts.map +1 -1
  142. package/dist/internal.mjs +23 -2
  143. package/dist/internal.mjs.map +1 -1
  144. package/dist/light-buffer-layout.d.ts +60 -148
  145. package/dist/light-buffer-layout.d.ts.map +1 -1
  146. package/dist/materials.d.ts +34 -10
  147. package/dist/materials.d.ts.map +1 -1
  148. package/dist/mesh-material-bindings.d.ts +56 -0
  149. package/dist/mesh-material-bindings.d.ts.map +1 -1
  150. package/dist/occlusion-proxy.d.ts +4 -0
  151. package/dist/occlusion-proxy.d.ts.map +1 -0
  152. package/dist/pbr-pipeline.d.ts +58 -21
  153. package/dist/pbr-pipeline.d.ts.map +1 -1
  154. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  155. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -1
  156. package/dist/pipeline/standard-lighting/light-frame.d.ts +3 -3
  157. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -1
  158. package/dist/pipeline/standard-lighting/topology.d.ts +1 -1
  159. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -1
  160. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -1
  161. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  162. package/dist/pipeline-builder.d.ts +2 -0
  163. package/dist/pipeline-builder.d.ts.map +1 -1
  164. package/dist/pipeline-spec.d.ts +1 -1
  165. package/dist/pipeline-spec.d.ts.map +1 -1
  166. package/dist/plugin.d.ts.map +1 -1
  167. package/dist/points-lines/prepare.d.ts +3 -0
  168. package/dist/points-lines/prepare.d.ts.map +1 -1
  169. package/dist/points-lines/standard-owner.d.ts +33 -0
  170. package/dist/points-lines/standard-owner.d.ts.map +1 -0
  171. package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
  172. package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
  173. package/dist/prepare/extended-lighting/resources.d.ts +72 -0
  174. package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
  175. package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
  176. package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
  177. package/dist/prepare/extended-lighting/state.d.ts +24 -0
  178. package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
  179. package/dist/record/frame-lighting.d.ts +8 -6
  180. package/dist/record/frame-lighting.d.ts.map +1 -1
  181. package/dist/record/frame-snapshot.d.ts +55 -10
  182. package/dist/record/frame-snapshot.d.ts.map +1 -1
  183. package/dist/record/frame-targets.d.ts.map +1 -1
  184. package/dist/record/frame.d.ts +21 -5
  185. package/dist/record/frame.d.ts.map +1 -1
  186. package/dist/record/gpu-timing.d.ts +19 -7
  187. package/dist/record/gpu-timing.d.ts.map +1 -1
  188. package/dist/record/helpers.d.ts +0 -20
  189. package/dist/record/helpers.d.ts.map +1 -1
  190. package/dist/record/main-pass-geometry.d.ts +20 -2
  191. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  192. package/dist/record/main-pass-material.d.ts +10 -18
  193. package/dist/record/main-pass-material.d.ts.map +1 -1
  194. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  195. package/dist/record/main-pass.d.ts.map +1 -1
  196. package/dist/record/mesh-ssbo.d.ts +11 -3
  197. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  198. package/dist/record/recovery-pipeline.d.ts +30 -0
  199. package/dist/record/recovery-pipeline.d.ts.map +1 -0
  200. package/dist/record/render-context.d.ts +82 -9
  201. package/dist/record/render-context.d.ts.map +1 -1
  202. package/dist/record/shadow-pass.d.ts.map +1 -1
  203. package/dist/record/typed-frame-graph.d.ts +49 -2
  204. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  205. package/dist/record/view-ubo.d.ts +1 -2
  206. package/dist/record/view-ubo.d.ts.map +1 -1
  207. package/dist/recovery/render-system-candidate.d.ts +65 -0
  208. package/dist/recovery/render-system-candidate.d.ts.map +1 -0
  209. package/dist/reflection/inspection.d.ts +10 -0
  210. package/dist/reflection/inspection.d.ts.map +1 -0
  211. package/dist/reflection/projection.d.ts +49 -0
  212. package/dist/reflection/projection.d.ts.map +1 -1
  213. package/dist/reflection/record-owner.d.ts +60 -0
  214. package/dist/reflection/record-owner.d.ts.map +1 -0
  215. package/dist/render-contract.d.ts +78 -15
  216. package/dist/render-contract.d.ts.map +1 -1
  217. package/dist/render-pipeline.d.ts +7 -0
  218. package/dist/render-pipeline.d.ts.map +1 -1
  219. package/dist/render-system-extract-tail.d.ts +12 -0
  220. package/dist/render-system-extract-tail.d.ts.map +1 -0
  221. package/dist/render-system-extract.d.ts +252 -30
  222. package/dist/render-system-extract.d.ts.map +1 -1
  223. package/dist/render-system.d.ts +140 -5
  224. package/dist/render-system.d.ts.map +1 -1
  225. package/dist/scene/probe-blend-record.d.ts +22 -0
  226. package/dist/scene/probe-blend-record.d.ts.map +1 -0
  227. package/dist/scene/probe-blend.d.ts +142 -0
  228. package/dist/scene/probe-blend.d.ts.map +1 -0
  229. package/dist/scene/render-scene-types.d.ts +0 -6
  230. package/dist/scene/render-scene-types.d.ts.map +1 -1
  231. package/dist/scene/render-scene.d.ts +122 -9
  232. package/dist/scene/render-scene.d.ts.map +1 -1
  233. package/dist/scene/visibility/bounds.d.ts +20 -0
  234. package/dist/scene/visibility/bounds.d.ts.map +1 -0
  235. package/dist/scene/visibility/budget.d.ts +16 -0
  236. package/dist/scene/visibility/budget.d.ts.map +1 -0
  237. package/dist/scene/visibility/facet.d.ts +73 -0
  238. package/dist/scene/visibility/facet.d.ts.map +1 -0
  239. package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
  240. package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
  241. package/dist/scene/visibility/gpu-lod.d.ts +46 -0
  242. package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
  243. package/dist/scene/visibility/inspection.d.ts +132 -0
  244. package/dist/scene/visibility/inspection.d.ts.map +1 -0
  245. package/dist/scene/visibility/lod-selector.d.ts +25 -0
  246. package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
  247. package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
  248. package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
  249. package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
  250. package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
  251. package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
  252. package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
  253. package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
  254. package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
  255. package/dist/scene/visibility/types.d.ts +34 -0
  256. package/dist/scene/visibility/types.d.ts.map +1 -0
  257. package/dist/ssr/admission.d.ts +122 -0
  258. package/dist/ssr/admission.d.ts.map +1 -0
  259. package/dist/ssr/composition.d.ts +32 -0
  260. package/dist/ssr/composition.d.ts.map +1 -0
  261. package/dist/ssr/errors.d.ts +39 -0
  262. package/dist/ssr/errors.d.ts.map +1 -0
  263. package/dist/ssr/identity.d.ts +13 -0
  264. package/dist/ssr/identity.d.ts.map +1 -0
  265. package/dist/systems/skin-palette-allocator.d.ts +1 -1
  266. package/dist/temporal/frame-coordinator.d.ts +13 -0
  267. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  268. package/dist/temporal/frame.d.ts +2 -0
  269. package/dist/temporal/frame.d.ts.map +1 -1
  270. package/dist/temporal/index.mjs +6 -5
  271. package/dist/temporal/taa-history-store.d.ts +15 -1
  272. package/dist/temporal/taa-history-store.d.ts.map +1 -1
  273. package/dist/temporal/transaction.d.ts +5 -0
  274. package/dist/temporal/transaction.d.ts.map +1 -1
  275. package/dist/temporal/view.d.ts +7 -0
  276. package/dist/temporal/view.d.ts.map +1 -1
  277. package/dist/tilemap-chunk-extract-system.d.ts +1 -1
  278. package/dist/typed-render-graph-primitives.d.ts +4 -0
  279. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  280. package/dist/volume/passes.d.ts +8 -4
  281. package/dist/volume/passes.d.ts.map +1 -1
  282. package/package.json +20 -20
  283. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +5 -0
  284. package/src/__tests__/detached-inspection.integration.test.ts +6 -0
  285. package/src/__tests__/device-feature-admission.unit.test.ts +19 -1
  286. package/src/__tests__/device-loss-fanout.unit.test.ts +107 -0
  287. package/src/__tests__/device-scope-lifecycle.unit.test.ts +21 -0
  288. package/src/__tests__/direct-light-snapshot.unit.test.ts +59 -3
  289. package/src/__tests__/environment-generation.integration.test.ts +39 -0
  290. package/src/__tests__/evidence-identity.ts +13 -0
  291. package/src/__tests__/evidence-identity.unit.test.ts +24 -0
  292. package/src/__tests__/expose-renderer-errors.unit.test.ts +34 -0
  293. package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
  294. package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
  295. package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
  296. package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
  297. package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
  298. package/src/__tests__/factory-contract.integration.test.ts +154 -6
  299. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +4 -1
  300. package/src/__tests__/frame-observation.contract.test.ts +15 -0
  301. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
  302. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +1 -0
  303. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +1 -0
  304. package/src/__tests__/gpu-driven-production.integration.test.ts +572 -9
  305. package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
  306. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
  307. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +89 -2
  308. package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
  309. package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
  310. package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
  311. package/src/__tests__/gpu-lod-evidence.ts +188 -0
  312. package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
  313. package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
  314. package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
  315. package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
  316. package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
  317. package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
  318. package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
  319. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
  320. package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
  321. package/src/__tests__/gpu-scene.unit.test.ts +49 -3
  322. package/src/__tests__/ibl/face-uniforms.unit.test.ts +2 -0
  323. package/src/__tests__/ibl-residency-publication.unit.test.ts +113 -0
  324. package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
  325. package/src/__tests__/light-inspection.unit.test.ts +55 -0
  326. package/src/__tests__/light-resource-error.unit.test.ts +43 -0
  327. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
  328. package/src/__tests__/lod-bounds.unit.test.ts +42 -0
  329. package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
  330. package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
  331. package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
  332. package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
  333. package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
  334. package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
  335. package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
  336. package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
  337. package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
  338. package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
  339. package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
  340. package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
  341. package/src/__tests__/lod-selector.profile.test.ts +35 -0
  342. package/src/__tests__/lod-selector.unit.test.ts +68 -0
  343. package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
  344. package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
  345. package/src/__tests__/ltc-resources.unit.test.ts +32 -0
  346. package/src/__tests__/material-contract-inventory.unit.test.ts +41 -9
  347. package/src/__tests__/material-cooked-projection.unit.test.ts +19 -1
  348. package/src/__tests__/material-static-dynamic-route.unit.test.ts +29 -0
  349. package/src/__tests__/material-stride-surface.unit.test.ts +7 -3
  350. package/src/__tests__/materials-standard-contract.unit.test.ts +104 -0
  351. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
  352. package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
  353. package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
  354. package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
  355. package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
  356. package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
  357. package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
  358. package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
  359. package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
  360. package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
  361. package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
  362. package/src/__tests__/occlusion-query.evidence.ts +178 -0
  363. package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
  364. package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
  365. package/src/__tests__/physical-clearcoat.integration.test.ts +89 -0
  366. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
  367. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +1 -1
  368. package/src/__tests__/probe-bindings.unit.test.ts +200 -0
  369. package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
  370. package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
  371. package/src/__tests__/probe-capacity.integration.test.ts +97 -0
  372. package/src/__tests__/probe-recovery.integration.test.ts +104 -0
  373. package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
  374. package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
  375. package/src/__tests__/profiler-phase-token.test.ts +1 -0
  376. package/src/__tests__/recover-error-policy-owner.unit.test.ts +6 -3
  377. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +140 -0
  378. package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
  379. package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
  380. package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
  381. package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
  382. package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
  383. package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
  384. package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
  385. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
  386. package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
  387. package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
  388. package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
  389. package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
  390. package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
  391. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +160 -17
  392. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +47 -0
  393. package/src/__tests__/renderer-generation-assembly.unit.test.ts +77 -0
  394. package/src/__tests__/renderer-generation-failure.unit.test.ts +108 -0
  395. package/src/__tests__/renderer-producer-root-matrix.integration.test.ts +33 -0
  396. package/src/__tests__/renderer-recovery-capability-matrix.unit.test.ts +59 -0
  397. package/src/__tests__/renderer-recovery-contract.unit.test.ts +73 -0
  398. package/src/__tests__/renderer-recovery-lifecycle.unit.test.ts +216 -0
  399. package/src/__tests__/renderer-target-history-recovery.integration.test.ts +80 -0
  400. package/src/__tests__/shader-manifest-fixture.ts +13 -16
  401. package/src/__tests__/shader-stage-surface.unit.test.ts +1 -1
  402. package/src/__tests__/skin-motion-regression.unit.test.ts +22 -0
  403. package/src/__tests__/skinned-shadow-caster.test.ts +2 -2
  404. package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
  405. package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
  406. package/src/__tests__/ssr-composition.unit.test.ts +46 -0
  407. package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
  408. package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
  409. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +67 -0
  410. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +7 -0
  411. package/src/__tests__/standard-layer-projection.unit.test.ts +23 -0
  412. package/src/__tests__/standard-lighting-inspection.integration.test.ts +1 -1
  413. package/src/__tests__/standard-lighting-write.unit.test.ts +66 -2
  414. package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
  415. package/src/__tests__/temporal-view.unit.test.ts +3 -3
  416. package/src/__tests__/transmission-prewarm.unit.test.ts +111 -32
  417. package/src/__tests__/visibility-budget.integration.test.ts +140 -0
  418. package/src/__tests__/visibility-budget.unit.test.ts +70 -0
  419. package/src/__tests__/visibility-extract.integration.test.ts +11 -6
  420. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
  421. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
  422. package/src/__tests__/volumetric-fog-topology.unit.test.ts +3 -1
  423. package/src/assembly/backend-contract.ts +13 -0
  424. package/src/assembly/bundler-contract.ts +9 -0
  425. package/src/assembly/device-feature-admission.ts +26 -9
  426. package/src/assembly/extended-lighting-fallback.ts +216 -0
  427. package/src/assembly/factory.ts +81 -9634
  428. package/src/assembly/host-contract.ts +10 -0
  429. package/src/assembly/material/assembly.ts +18 -2
  430. package/src/assembly/material/standard-layer-projection.ts +16 -0
  431. package/src/assembly/material-shader-policy.ts +854 -0
  432. package/src/assembly/material-shader-prewarm.ts +88 -0
  433. package/src/assembly/mesh-ssbo-grow.ts +270 -0
  434. package/src/assembly/recovery/device-loss-fanout.ts +89 -0
  435. package/src/assembly/recovery/generation.ts +141 -0
  436. package/src/assembly/recovery/recovery-attempt.ts +800 -0
  437. package/src/assembly/recovery/renderer-recover.ts +906 -0
  438. package/src/assembly/renderer-facade.ts +342 -0
  439. package/src/assembly/renderer-frame-transaction.ts +45 -0
  440. package/src/assembly/renderer-helpers.ts +99 -0
  441. package/src/assembly/renderer-lifecycle.ts +159 -0
  442. package/src/assembly/shader-prewarm-policy.ts +157 -0
  443. package/src/assembly/webgpu-ready-contract.ts +14 -0
  444. package/src/assembly/webgpu-ready.ts +4079 -0
  445. package/src/assembly/webgpu-renderer.ts +4095 -0
  446. package/src/cluster-binner.ts +31 -0
  447. package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
  448. package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
  449. package/src/components/camera.ts +1 -1
  450. package/src/components/index.ts +3 -0
  451. package/src/components/light-helpers.ts +52 -1
  452. package/src/components/light-probe.ts +13 -0
  453. package/src/components/rect-area-light.ts +15 -0
  454. package/src/components/scene-instance.ts +6 -0
  455. package/src/components/spot-light.ts +3 -0
  456. package/src/debug-draw-glue.ts +1 -1
  457. package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
  458. package/src/device/device-scope.ts +35 -6
  459. package/src/device/gpu-residency.ts +334 -35
  460. package/src/device/lifecycle-transaction.ts +12 -0
  461. package/src/environment/frame.ts +6 -0
  462. package/src/environment/inspection.ts +10 -0
  463. package/src/environment/lifecycle.ts +122 -9
  464. package/src/errors/gpu-driven.ts +92 -0
  465. package/src/errors/index.ts +1 -0
  466. package/src/errors/recover.ts +108 -5
  467. package/src/errors/render.ts +72 -1
  468. package/src/extract/camera.ts +3 -3
  469. package/src/extract/contracts.ts +974 -0
  470. package/src/extract/gpu-driven.ts +108 -0
  471. package/src/extract/visibility.ts +0 -23
  472. package/src/features/host.ts +16 -0
  473. package/src/features/prepared-gpu-work.ts +20 -2
  474. package/src/features/prepared-graphics-store.ts +17 -0
  475. package/src/gpu-driven/batch-topology.ts +206 -28
  476. package/src/gpu-driven/prepared-draw.ts +208 -0
  477. package/src/gpu-driven/production-raster.ts +1046 -39
  478. package/src/gpu-driven/view-gpu.ts +411 -29
  479. package/src/gpu-scene-schema.ts +13 -0
  480. package/src/gpu-scene.ts +137 -67
  481. package/src/gpu-usage.ts +0 -1
  482. package/src/hdrp-buffers.ts +6 -6
  483. package/src/ibl/IblPipelineCache.ts +134 -50
  484. package/src/ibl/skylight-bind-group.ts +26 -0
  485. package/src/index.ts +83 -1
  486. package/src/inspection-types.ts +220 -1
  487. package/src/internal.ts +38 -0
  488. package/src/light-buffer-layout.ts +157 -324
  489. package/src/materials.ts +278 -47
  490. package/src/mesh-material-bindings.ts +59 -0
  491. package/src/occlusion-proxy.ts +64 -0
  492. package/src/pbr-pipeline.ts +290 -60
  493. package/src/pipeline/standard-forward-lane.ts +47 -0
  494. package/src/pipeline/standard-lighting/graph.ts +2 -1
  495. package/src/pipeline/standard-lighting/light-frame.ts +3 -2
  496. package/src/pipeline/standard-lighting/topology.ts +1 -1
  497. package/src/pipeline/standard-lighting/transport.ts +2 -1
  498. package/src/pipeline/standard-pipeline.ts +2 -0
  499. package/src/pipeline-builder.ts +5 -2
  500. package/src/pipeline-spec.ts +12 -1
  501. package/src/plugin.ts +4 -0
  502. package/src/points-lines/__tests__/cache-recovery.unit.test.ts +22 -0
  503. package/src/points-lines/prepare.ts +9 -0
  504. package/src/points-lines/standard-owner.ts +403 -0
  505. package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
  506. package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
  507. package/src/prepare/extended-lighting/resources.ts +389 -0
  508. package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
  509. package/src/prepare/extended-lighting/state.ts +92 -0
  510. package/src/record/__tests__/frame-targets-recovery.unit.test.ts +60 -0
  511. package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
  512. package/src/record/__tests__/main-pass-geometry.unit.test.ts +26 -1
  513. package/src/record/__tests__/mesh-ssbo.unit.test.ts +38 -0
  514. package/src/record/__tests__/recovery-pipeline.unit.test.ts +124 -0
  515. package/src/record/__tests__/sprite-material-abi.unit.test.ts +28 -13
  516. package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +47 -4
  517. package/src/record/__tests__/temporal-payload.unit.test.ts +29 -28
  518. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +21 -2
  519. package/src/record/frame-lighting.ts +252 -53
  520. package/src/record/frame-snapshot.ts +72 -12
  521. package/src/record/frame-targets.ts +11 -1
  522. package/src/record/frame.ts +416 -95
  523. package/src/record/gpu-timing.ts +108 -44
  524. package/src/record/helpers.ts +1 -59
  525. package/src/record/main-pass-geometry.ts +434 -44
  526. package/src/record/main-pass-material.ts +324 -210
  527. package/src/record/main-pass-sprite-draws.ts +58 -92
  528. package/src/record/main-pass.ts +94 -6
  529. package/src/record/mesh-ssbo.ts +79 -46
  530. package/src/record/recovery-pipeline.ts +695 -0
  531. package/src/record/render-context.ts +99 -7
  532. package/src/record/shadow-pass.ts +66 -40
  533. package/src/record/typed-frame-graph.ts +270 -84
  534. package/src/record/view-ubo.ts +17 -27
  535. package/src/recovery/render-system-candidate.ts +839 -0
  536. package/src/reflection/inspection.ts +67 -0
  537. package/src/reflection/projection.ts +196 -1
  538. package/src/reflection/record-owner.ts +1283 -0
  539. package/src/render-contract.ts +82 -12
  540. package/src/render-pipeline.ts +5 -0
  541. package/src/render-system-extract-tail.ts +2983 -0
  542. package/src/render-system-extract.ts +290 -2784
  543. package/src/render-system.ts +1597 -1192
  544. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
  545. package/src/scene/probe-blend-record.ts +54 -0
  546. package/src/scene/probe-blend.ts +813 -0
  547. package/src/scene/render-scene-types.ts +0 -7
  548. package/src/scene/render-scene.ts +972 -184
  549. package/src/scene/visibility/bounds.ts +57 -0
  550. package/src/scene/visibility/budget.ts +40 -0
  551. package/src/scene/visibility/facet.ts +400 -0
  552. package/src/scene/visibility/gpu-frame-timing.ts +101 -0
  553. package/src/scene/visibility/gpu-lod.ts +119 -0
  554. package/src/scene/visibility/inspection.ts +313 -0
  555. package/src/scene/visibility/lod-selector.ts +84 -0
  556. package/src/scene/visibility/occlusion-confidence.ts +478 -0
  557. package/src/scene/visibility/occlusion-pass.ts +165 -0
  558. package/src/scene/visibility/occlusion-query-pool.ts +178 -0
  559. package/src/scene/visibility/occlusion-runtime.ts +672 -0
  560. package/src/scene/visibility/types.ts +50 -0
  561. package/src/ssr/admission.ts +451 -0
  562. package/src/ssr/composition.ts +73 -0
  563. package/src/ssr/errors.ts +76 -0
  564. package/src/ssr/identity.ts +12 -0
  565. package/src/systems/skin-palette-allocator.ts +1 -1
  566. package/src/temporal/frame-coordinator.ts +30 -1
  567. package/src/temporal/frame.ts +14 -1
  568. package/src/temporal/taa-history-store.ts +46 -2
  569. package/src/temporal/temporal-view.ts +1 -1
  570. package/src/temporal/transaction.ts +9 -0
  571. package/src/temporal/view.ts +11 -0
  572. package/src/tilemap-chunk-extract-system.ts +5 -5
  573. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +19 -12
  574. package/src/typed-render-graph-primitives.ts +48 -0
  575. package/src/volume/passes.ts +46 -49
  576. package/dist/.tsbuildinfo +0 -1
  577. package/dist/chunk-5YADUCA7.mjs.map +0 -1
  578. package/dist/chunk-6OPXDQ2E.mjs.map +0 -1
  579. package/dist/chunk-BXBQQKFQ.mjs +0 -67
  580. package/dist/chunk-BXBQQKFQ.mjs.map +0 -1
  581. package/dist/chunk-FS2KNUQH.mjs.map +0 -1
  582. package/dist/chunk-PCHBPYML.mjs.map +0 -1
  583. package/dist/chunk-VFPLTKCU.mjs +0 -192
  584. package/dist/chunk-VFPLTKCU.mjs.map +0 -1
@@ -0,0 +1,695 @@
1
+ import {
2
+ deriveVertexLayoutProjection,
3
+ type VertexLayoutProjection,
4
+ } from '@forgeax/engine-geometry';
5
+ import type {
6
+ MaterialRenderState,
7
+ PassKind,
8
+ PrimitiveTopology,
9
+ VertexAttributeMap,
10
+ } from '@forgeax/engine-types';
11
+ import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from '../materials';
12
+ import {
13
+ isStandardPbrMaterialShader,
14
+ SHADOW_CASTER_SHADER_ID,
15
+ SKIN_MATERIAL_SHADER_ID,
16
+ SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET,
17
+ shadowCasterVariantSet,
18
+ } from '../pbr-pipeline';
19
+ import type { StandardTopologyInputValue } from '../pipeline/standard-lighting/topology';
20
+ import {
21
+ cacheKeyOf,
22
+ colorFormatsForPassKind,
23
+ type PipelineSpec,
24
+ PipelineSpecError,
25
+ standardStorageVariantSet,
26
+ standardTopologyVariantSet,
27
+ variantSetFromVertexLayoutProjection,
28
+ } from '../pipeline-spec';
29
+ import { POINTS_LINES_MATERIAL_SHADER_ID } from '../points-lines/record';
30
+ import type { CameraSnapshot } from '../render-contract';
31
+ import type { DispatchEntry, MaterialSnapshot } from '../render-system-extract';
32
+ import type { ValidatedRenderable } from './frame-snapshot';
33
+ import { geometryRenderStateForPass } from './main-pass-geometry';
34
+ import { geometryRenderStateForTopology } from './main-pass-material';
35
+ import type {
36
+ MaterialShaderPipelineEntry,
37
+ PipelineState,
38
+ RecoveryColdWorkGuard,
39
+ RenderSystemInternals,
40
+ } from './render-context';
41
+
42
+ export interface RecoveryPipelineReadiness {
43
+ readonly pipelineSpecs: readonly PipelineSpec[];
44
+ /** Re-resolve every candidate request and assert a stable cache hit. */
45
+ readonly assertFirstRecoveryFrame: () => void;
46
+ }
47
+
48
+ /**
49
+ * Create the one-shot assertion used by the first frame after publication.
50
+ * Recording a miss is a failure at the owner seam; the draw path never gets a
51
+ * chance to submit a frame that hides a shader/pipeline or static-residency
52
+ * cold build behind an apparently successful receipt.
53
+ */
54
+ export function createRecoveryColdWorkGuard(): RecoveryColdWorkGuard {
55
+ let armed = false;
56
+ let finished = false;
57
+ let pipelineColdWork = 0;
58
+ let uploadColdWork = 0;
59
+ const fail = (kind: 'pipeline' | 'upload'): never => {
60
+ if (kind === 'pipeline') pipelineColdWork += 1;
61
+ else uploadColdWork += 1;
62
+ throw new Error(
63
+ `recovery first frame performed cold ${kind} work ` +
64
+ `(pipeline=${pipelineColdWork}, upload=${uploadColdWork})`,
65
+ );
66
+ };
67
+ return {
68
+ arm(): void {
69
+ armed = true;
70
+ finished = false;
71
+ pipelineColdWork = 0;
72
+ uploadColdWork = 0;
73
+ },
74
+ notePipelineColdWork(): void {
75
+ if (armed && !finished) fail('pipeline');
76
+ },
77
+ noteUploadColdWork(): void {
78
+ if (armed && !finished) fail('upload');
79
+ },
80
+ finish(): void {
81
+ if (!armed || finished) return;
82
+ finished = true;
83
+ armed = false;
84
+ if (pipelineColdWork !== 0 || uploadColdWork !== 0) {
85
+ throw new Error(
86
+ `recovery first frame cold-work assertion failed ` +
87
+ `(pipeline=${pipelineColdWork}, upload=${uploadColdWork})`,
88
+ );
89
+ }
90
+ },
91
+ };
92
+ }
93
+
94
+ interface RecoveryPipelineRequest {
95
+ readonly spec: PipelineSpec;
96
+ readonly resolve: () => MaterialShaderPipelineEntry | null;
97
+ }
98
+
99
+ const DEFAULT_VERTEX_ATTRIBUTES: VertexAttributeMap = {
100
+ position: new Float32Array(0),
101
+ normal: new Float32Array(0),
102
+ uv: new Float32Array(0),
103
+ tangent: new Float32Array(0),
104
+ };
105
+
106
+ function optionalRenderState(
107
+ state: MaterialRenderState | undefined,
108
+ ): { readonly renderState: MaterialRenderState } | Record<string, never> {
109
+ return state === undefined ? {} : { renderState: state };
110
+ }
111
+
112
+ function optionalVariant(
113
+ variant: string | undefined,
114
+ ): { readonly variantSet: string } | Record<string, never> {
115
+ return variant === undefined ? {} : { variantSet: variant };
116
+ }
117
+
118
+ function optionalColorFormat(
119
+ format: GPUTextureFormat | undefined,
120
+ ): { readonly colorFormatOverride: GPUTextureFormat } | Record<string, never> {
121
+ return format === undefined ? {} : { colorFormatOverride: format };
122
+ }
123
+
124
+ function projectionVariant(
125
+ projection: VertexLayoutProjection,
126
+ requested: string | undefined,
127
+ preserveUndefined = false,
128
+ ): string | undefined {
129
+ if (preserveUndefined && requested === undefined) return undefined;
130
+ const resolved = variantSetFromVertexLayoutProjection(projection, requested);
131
+ if (!resolved.ok) {
132
+ throw new PipelineSpecError({
133
+ code: 'spec-inconsistent',
134
+ detail: { reason: resolved.error.message },
135
+ hint: 'recovery candidate variant must agree with the LKG vertex layout projection',
136
+ });
137
+ }
138
+ return resolved.value;
139
+ }
140
+
141
+ function recoveryRenderState(
142
+ materialShaderId: string,
143
+ material: MaterialSnapshot,
144
+ topology: PrimitiveTopology,
145
+ ): MaterialRenderState | undefined {
146
+ const sprite =
147
+ materialShaderId === 'forgeax::sprite' || materialShaderId === 'forgeax::sprite-lit';
148
+ if (sprite) {
149
+ return {
150
+ ...material.renderState,
151
+ depthWriteEnabled: false,
152
+ depthCompare: 'less-equal',
153
+ cullMode: 'none',
154
+ blend: material.renderState?.blend ?? SPRITE_PREMULTIPLIED_ALPHA_BLEND,
155
+ };
156
+ }
157
+ return geometryRenderStateForTopology(topology, material.renderState);
158
+ }
159
+
160
+ function addRequest(input: {
161
+ readonly requests: RecoveryPipelineRequest[];
162
+ readonly requestKeys: Set<string>;
163
+ readonly internals: RenderSystemInternals;
164
+ readonly pipelineState: PipelineState;
165
+ readonly materialShaderId: string;
166
+ readonly isHdrTarget: boolean;
167
+ readonly renderState?: MaterialRenderState;
168
+ readonly topology?: PrimitiveTopology;
169
+ readonly indexFormat?: 'uint16' | 'uint32';
170
+ readonly variantSet?: string;
171
+ readonly passKind?: PassKind;
172
+ readonly sampleCount?: number;
173
+ readonly colorFormatOverride?: GPUTextureFormat;
174
+ readonly additionalColorFormats?: readonly GPUTextureFormat[];
175
+ readonly depthFormatOverride?: GPUTextureFormat | null;
176
+ readonly vertexLayoutProjection?: VertexLayoutProjection;
177
+ readonly preserveUndefinedVariant?: boolean;
178
+ readonly variantAlreadyResolved?: boolean;
179
+ }): void {
180
+ const passKind = input.passKind ?? 'forward';
181
+ const projection = input.vertexLayoutProjection;
182
+ const resolvedVariantSet =
183
+ input.variantAlreadyResolved === true
184
+ ? input.variantSet
185
+ : projection === undefined
186
+ ? input.variantSet
187
+ : projectionVariant(projection, input.variantSet, input.preserveUndefinedVariant === true);
188
+ const colorFormat = input.isHdrTarget
189
+ ? 'rgba16float'
190
+ : (input.colorFormatOverride ?? input.pipelineState.colorAttachmentFormat);
191
+ const colorFormats =
192
+ input.additionalColorFormats === undefined
193
+ ? colorFormatsForPassKind(passKind, colorFormat)
194
+ : [colorFormat, ...input.additionalColorFormats];
195
+ const depthFormat =
196
+ passKind === 'shadow-caster' || passKind === 'point-shadow-caster'
197
+ ? 'depth32float'
198
+ : input.depthFormatOverride === null
199
+ ? undefined
200
+ : (input.depthFormatOverride ?? 'depth24plus-stencil8');
201
+ const shaderUvSetCount = input.internals.getMaterialShaderUvSetCount?.(input.materialShaderId);
202
+ const spec: PipelineSpec = Object.freeze({
203
+ shader: Object.freeze({
204
+ id: input.materialShaderId,
205
+ passKind,
206
+ variantSet: resolvedVariantSet,
207
+ }),
208
+ attachments: Object.freeze({
209
+ colorFormats: Object.freeze([...colorFormats]),
210
+ depthFormat,
211
+ sampleCount: (input.sampleCount === 4 ? 4 : 1) as 1 | 4,
212
+ }),
213
+ geometry: Object.freeze({
214
+ topology: input.topology ?? 'triangle-list',
215
+ stripIndexFormat: input.indexFormat,
216
+ vertexLayout: DEFAULT_VERTEX_ATTRIBUTES,
217
+ ...(projection === undefined ? {} : { vertexLayoutProjection: projection }),
218
+ ...(shaderUvSetCount !== undefined && shaderUvSetCount > 1
219
+ ? {
220
+ shaderUvSetCount,
221
+ }
222
+ : {}),
223
+ }),
224
+ renderState: input.renderState,
225
+ });
226
+ const key = cacheKeyOf(spec);
227
+ if (input.requestKeys.has(key)) return;
228
+ input.requestKeys.add(key);
229
+ const resolve = (): MaterialShaderPipelineEntry | null =>
230
+ input.internals.getMaterialShaderPipelineEntry?.(
231
+ input.materialShaderId,
232
+ input.isHdrTarget,
233
+ input.renderState,
234
+ input.topology,
235
+ input.indexFormat,
236
+ resolvedVariantSet,
237
+ passKind,
238
+ undefined,
239
+ input.sampleCount,
240
+ input.colorFormatOverride,
241
+ undefined,
242
+ undefined,
243
+ undefined,
244
+ projection,
245
+ undefined,
246
+ undefined,
247
+ input.additionalColorFormats,
248
+ ) ?? null;
249
+ input.requests.push({ spec, resolve });
250
+ }
251
+
252
+ function addStandardMaterialRequests(input: {
253
+ readonly requests: RecoveryPipelineRequest[];
254
+ readonly requestKeys: Set<string>;
255
+ readonly internals: RenderSystemInternals;
256
+ readonly pipelineState: PipelineState;
257
+ readonly validated: readonly ValidatedRenderable[];
258
+ readonly standardLighting: StandardTopologyInputValue | undefined;
259
+ readonly sampleCount: number;
260
+ readonly isHdrTarget: boolean;
261
+ readonly colorFormatOverride?: GPUTextureFormat;
262
+ readonly reflectionFallbackAvailable: boolean;
263
+ }): void {
264
+ const pointsLinesProjection = deriveVertexLayoutProjection({
265
+ position: new Float32Array(0),
266
+ normal: new Float32Array(0),
267
+ uv: new Float32Array(0),
268
+ tangent: new Float32Array(0),
269
+ });
270
+ for (const entry of input.validated) {
271
+ if (entry.source.pointsLines !== undefined) {
272
+ const pointsLinesMaterial = entry.source.material;
273
+ addRequest({
274
+ requests: input.requests,
275
+ requestKeys: input.requestKeys,
276
+ internals: input.internals,
277
+ pipelineState: input.pipelineState,
278
+ materialShaderId: POINTS_LINES_MATERIAL_SHADER_ID,
279
+ isHdrTarget: input.isHdrTarget,
280
+ renderState: {
281
+ ...pointsLinesMaterial.renderState,
282
+ cullMode: 'none',
283
+ },
284
+ topology: 'triangle-list',
285
+ indexFormat: 'uint32',
286
+ sampleCount: input.sampleCount,
287
+ ...optionalColorFormat(input.colorFormatOverride),
288
+ vertexLayoutProjection: pointsLinesProjection,
289
+ });
290
+ continue;
291
+ }
292
+ const meshProjection = entry.mesh.layoutProjection;
293
+ const hasVertexColor = meshProjection.attributes.some((attribute) => attribute.key === 'color');
294
+ const capabilityVariantSet = standardTopologyVariantSet(
295
+ input.standardLighting,
296
+ input.internals.device.caps.storageBuffer,
297
+ hasVertexColor,
298
+ );
299
+ // The probe record is an object-level ABI extension of the built-in
300
+ // Standard PBR family. Recovery must request the same variant that the
301
+ // live record path will select, otherwise the first post-recovery draw
302
+ // discovers a cold PSO and the cold-work guard correctly rejects it.
303
+ const probeBlendRecordAvailable =
304
+ input.internals.device.caps.storageBuffer && entry.source.probeBlendRecord !== undefined;
305
+ const standardPbrCapabilityVariantSet = standardTopologyVariantSet(
306
+ input.standardLighting,
307
+ input.internals.device.caps.storageBuffer,
308
+ hasVertexColor,
309
+ probeBlendRecordAvailable,
310
+ );
311
+ const unlitProjection = projectionVariant(meshProjection, undefined);
312
+ const unlitHasColor = unlitProjection === 'VERTEX_COLOR_AVAILABLE=true';
313
+ for (const submesh of entry.mesh.submeshes) {
314
+ const material = entry.source.materials[submesh.materialSlot] ?? entry.source.material;
315
+ const materialShaderId =
316
+ entry.source.skin === undefined
317
+ ? (material.materialShaderId ?? 'forgeax::default-unlit')
318
+ : SKIN_MATERIAL_SHADER_ID;
319
+ const renderState = geometryRenderStateForPass(
320
+ recoveryRenderState(materialShaderId, material, submesh.topology) as ReturnType<
321
+ typeof geometryRenderStateForTopology
322
+ >,
323
+ 'forward',
324
+ );
325
+ if (entry.source.skin !== undefined && submesh === entry.mesh.submeshes[0]) {
326
+ const skinProbeVariant = projectionVariant(meshProjection, standardPbrCapabilityVariantSet);
327
+ addRequest({
328
+ requests: input.requests,
329
+ requestKeys: input.requestKeys,
330
+ internals: input.internals,
331
+ pipelineState: input.pipelineState,
332
+ materialShaderId: SKIN_MATERIAL_SHADER_ID,
333
+ isHdrTarget: input.isHdrTarget,
334
+ ...optionalRenderState(entry.source.material.renderState),
335
+ topology: entry.mesh.submeshes[0]?.topology ?? 'triangle-list',
336
+ indexFormat: entry.mesh.indexFormat,
337
+ ...optionalVariant(skinProbeVariant),
338
+ sampleCount: input.sampleCount,
339
+ ...optionalColorFormat(input.colorFormatOverride),
340
+ vertexLayoutProjection: meshProjection,
341
+ variantAlreadyResolved: true,
342
+ });
343
+ }
344
+ if (
345
+ materialShaderId === 'forgeax::default-unlit' ||
346
+ materialShaderId === 'forgeax::default-standard-unlit'
347
+ ) {
348
+ addRequest({
349
+ requests: input.requests,
350
+ requestKeys: input.requestKeys,
351
+ internals: input.internals,
352
+ pipelineState: input.pipelineState,
353
+ materialShaderId,
354
+ isHdrTarget: input.isHdrTarget,
355
+ ...optionalRenderState(renderState),
356
+ topology: submesh.topology,
357
+ indexFormat: entry.mesh.indexFormat,
358
+ variantSet: standardStorageVariantSet(
359
+ input.internals.device.caps.storageBuffer,
360
+ unlitHasColor,
361
+ ),
362
+ sampleCount: input.sampleCount,
363
+ ...optionalColorFormat(input.colorFormatOverride),
364
+ vertexLayoutProjection: meshProjection,
365
+ });
366
+ continue;
367
+ }
368
+ const isSprite =
369
+ materialShaderId === 'forgeax::sprite' || materialShaderId === 'forgeax::sprite-lit';
370
+ const materialCapabilityVariantSet = isStandardPbrMaterialShader(materialShaderId)
371
+ ? standardPbrCapabilityVariantSet
372
+ : capabilityVariantSet;
373
+ const requestedVariant = isSprite
374
+ ? materialShaderId === 'forgeax::sprite' && entry.source.spriteInstances !== undefined
375
+ ? SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET
376
+ : undefined
377
+ : entry.variantSet === undefined
378
+ ? materialCapabilityVariantSet
379
+ : materialCapabilityVariantSet === ''
380
+ ? entry.variantSet
381
+ : `${materialCapabilityVariantSet}+${entry.variantSet}`;
382
+ const reflectionFallbackVariant =
383
+ input.reflectionFallbackAvailable && materialShaderId === 'forgeax::default-standard-pbr'
384
+ ? (() => {
385
+ const projected = projectionVariant(meshProjection, requestedVariant);
386
+ return projected === ''
387
+ ? projected
388
+ : `${projected}+REFLECTION_FALLBACK_AVAILABLE=true`;
389
+ })()
390
+ : requestedVariant;
391
+ addRequest({
392
+ requests: input.requests,
393
+ requestKeys: input.requestKeys,
394
+ internals: input.internals,
395
+ pipelineState: input.pipelineState,
396
+ materialShaderId,
397
+ isHdrTarget: input.isHdrTarget,
398
+ ...optionalRenderState(renderState),
399
+ topology: submesh.topology,
400
+ indexFormat: entry.mesh.indexFormat,
401
+ ...optionalVariant(reflectionFallbackVariant),
402
+ passKind: 'forward',
403
+ sampleCount: input.sampleCount,
404
+ ...optionalColorFormat(input.colorFormatOverride),
405
+ ...(input.reflectionFallbackAvailable &&
406
+ materialShaderId === 'forgeax::default-standard-pbr'
407
+ ? { additionalColorFormats: ['rgba16float'] as const }
408
+ : {}),
409
+ vertexLayoutProjection: meshProjection,
410
+ preserveUndefinedVariant: isSprite && requestedVariant === undefined,
411
+ variantAlreadyResolved:
412
+ isSprite ||
413
+ (input.reflectionFallbackAvailable &&
414
+ materialShaderId === 'forgeax::default-standard-pbr'),
415
+ });
416
+ }
417
+ }
418
+ }
419
+
420
+ function addTransparentSpriteRequests(input: {
421
+ readonly requests: RecoveryPipelineRequest[];
422
+ readonly requestKeys: Set<string>;
423
+ readonly internals: RenderSystemInternals;
424
+ readonly pipelineState: PipelineState;
425
+ readonly validated: readonly ValidatedRenderable[];
426
+ readonly standardLighting: StandardTopologyInputValue | undefined;
427
+ readonly sampleCount: number;
428
+ readonly isHdrTarget: boolean;
429
+ readonly colorFormat: GPUTextureFormat;
430
+ }): void {
431
+ const spriteRenderState: MaterialRenderState = {
432
+ depthWriteEnabled: false,
433
+ depthCompare: 'less-equal',
434
+ cullMode: 'none',
435
+ blend: SPRITE_PREMULTIPLIED_ALPHA_BLEND,
436
+ };
437
+ // recordSpritePass resolves all three built-in sprite pipelines before it
438
+ // walks the visible entities. A generic transparent material is enough to
439
+ // enter that pass, so candidate preparation must warm the same complete
440
+ // request set even when the LKG contains no sprite entity. These calls also
441
+ // intentionally omit vertexLayoutProjection: the record path omits that
442
+ // argument and the factory's default sprite layout is the cache identity.
443
+ for (const request of [
444
+ {
445
+ materialShaderId: 'forgeax::sprite',
446
+ variantSet: undefined,
447
+ preserveUndefinedVariant: true,
448
+ },
449
+ {
450
+ materialShaderId: 'forgeax::sprite',
451
+ variantSet: SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET,
452
+ preserveUndefinedVariant: false,
453
+ },
454
+ {
455
+ materialShaderId: 'forgeax::sprite-lit',
456
+ variantSet: standardTopologyVariantSet(
457
+ input.standardLighting,
458
+ input.internals.device.caps.storageBuffer,
459
+ false,
460
+ ),
461
+ preserveUndefinedVariant: false,
462
+ },
463
+ ] as const) {
464
+ addRequest({
465
+ requests: input.requests,
466
+ requestKeys: input.requestKeys,
467
+ internals: input.internals,
468
+ pipelineState: input.pipelineState,
469
+ materialShaderId: request.materialShaderId,
470
+ isHdrTarget: input.isHdrTarget,
471
+ renderState: spriteRenderState,
472
+ topology: 'triangle-list',
473
+ ...optionalVariant(request.variantSet),
474
+ sampleCount: input.sampleCount,
475
+ colorFormatOverride: input.colorFormat,
476
+ preserveUndefinedVariant: request.preserveUndefinedVariant,
477
+ variantAlreadyResolved: true,
478
+ });
479
+ }
480
+
481
+ for (const entry of input.validated) {
482
+ const entityShaderId = entry.source.material.materialShaderId;
483
+ if (
484
+ entityShaderId === 'forgeax::sprite' ||
485
+ entityShaderId === 'forgeax::sprite-lit' ||
486
+ entry.source.skin !== undefined ||
487
+ entry.source.instances !== undefined
488
+ ) {
489
+ continue;
490
+ }
491
+ const projectedVariant = projectionVariant(
492
+ entry.mesh.layoutProjection,
493
+ standardTopologyVariantSet(
494
+ input.standardLighting,
495
+ input.internals.device.caps.storageBuffer,
496
+ entry.mesh.layoutProjection.attributes.some((attribute) => attribute.key === 'color'),
497
+ ),
498
+ );
499
+ for (const submesh of entry.mesh.submeshes) {
500
+ const material = entry.source.materials[submesh.materialSlot] ?? entry.source.material;
501
+ if (material.transparent !== true || material.materialShaderId === undefined) continue;
502
+ addRequest({
503
+ requests: input.requests,
504
+ requestKeys: input.requestKeys,
505
+ internals: input.internals,
506
+ pipelineState: input.pipelineState,
507
+ materialShaderId: material.materialShaderId,
508
+ isHdrTarget: input.isHdrTarget,
509
+ ...optionalRenderState(material.renderState),
510
+ topology: submesh.topology,
511
+ indexFormat: entry.mesh.indexFormat,
512
+ ...optionalVariant(projectedVariant),
513
+ sampleCount: input.sampleCount,
514
+ colorFormatOverride: input.colorFormat,
515
+ vertexLayoutProjection: entry.mesh.layoutProjection,
516
+ variantAlreadyResolved: true,
517
+ });
518
+ }
519
+ }
520
+ }
521
+
522
+ function addShadowRequests(input: {
523
+ readonly requests: RecoveryPipelineRequest[];
524
+ readonly requestKeys: Set<string>;
525
+ readonly internals: RenderSystemInternals;
526
+ readonly pipelineState: PipelineState;
527
+ readonly validated: readonly ValidatedRenderable[];
528
+ readonly dispatch: readonly DispatchEntry[];
529
+ }): void {
530
+ addRequest({
531
+ requests: input.requests,
532
+ requestKeys: input.requestKeys,
533
+ internals: input.internals,
534
+ pipelineState: input.pipelineState,
535
+ materialShaderId: SHADOW_CASTER_SHADER_ID,
536
+ isHdrTarget: false,
537
+ topology: 'triangle-list',
538
+ variantSet: shadowCasterVariantSet(input.internals.device.caps.storageBuffer, false),
539
+ passKind: 'shadow-caster',
540
+ sampleCount: 1,
541
+ variantAlreadyResolved: true,
542
+ });
543
+ const customByRenderable = new Map<
544
+ number,
545
+ Map<number, { id: string; state: MaterialRenderState | undefined }>
546
+ >();
547
+ for (const dispatch of input.dispatch) {
548
+ if (dispatch.tags.LightMode !== 'ShadowCaster' || dispatch.materialShaderId === undefined)
549
+ continue;
550
+ let materials = customByRenderable.get(dispatch.renderableIndex);
551
+ if (materials === undefined) {
552
+ materials = new Map();
553
+ customByRenderable.set(dispatch.renderableIndex, materials);
554
+ }
555
+ materials.set(dispatch.materialHandle, {
556
+ id: dispatch.materialShaderId,
557
+ state: dispatch.renderState,
558
+ });
559
+ }
560
+ for (const entry of input.validated) {
561
+ const triangles = entry.mesh.submeshes.filter(
562
+ (submesh) => submesh.topology === 'triangle-list' || submesh.topology === 'triangle-strip',
563
+ );
564
+ if (triangles.length === 0) continue;
565
+ if (entry.source.skin !== undefined) {
566
+ addRequest({
567
+ requests: input.requests,
568
+ requestKeys: input.requestKeys,
569
+ internals: input.internals,
570
+ pipelineState: input.pipelineState,
571
+ materialShaderId: SHADOW_CASTER_SHADER_ID,
572
+ isHdrTarget: false,
573
+ topology: entry.mesh.submeshes[0]?.topology ?? 'triangle-list',
574
+ indexFormat: entry.mesh.indexFormat,
575
+ variantSet: shadowCasterVariantSet(input.internals.device.caps.storageBuffer, true),
576
+ passKind: 'shadow-caster',
577
+ sampleCount: 1,
578
+ vertexLayoutProjection: entry.mesh.layoutProjection,
579
+ variantAlreadyResolved: true,
580
+ });
581
+ }
582
+ for (const submesh of triangles) {
583
+ const material = entry.source.materials[submesh.materialSlot] ?? entry.source.material;
584
+ const custom = customByRenderable
585
+ .get(entry.renderableIndex)
586
+ ?.get(material.materialHandle ?? 0);
587
+ if (
588
+ entry.source.skin === undefined &&
589
+ custom !== undefined &&
590
+ (custom.id !== 'forgeax::default-shadow-caster' || custom.state !== undefined)
591
+ ) {
592
+ addRequest({
593
+ requests: input.requests,
594
+ requestKeys: input.requestKeys,
595
+ internals: input.internals,
596
+ pipelineState: input.pipelineState,
597
+ materialShaderId: custom.id,
598
+ isHdrTarget: false,
599
+ ...optionalRenderState(custom.state),
600
+ topology: 'triangle-list',
601
+ passKind: 'shadow-caster',
602
+ sampleCount: 1,
603
+ preserveUndefinedVariant: true,
604
+ variantAlreadyResolved: true,
605
+ });
606
+ }
607
+ }
608
+ }
609
+ }
610
+
611
+ export function prepareRecoveryPipelineReadiness(input: {
612
+ readonly internals: RenderSystemInternals;
613
+ readonly pipelineState: PipelineState;
614
+ readonly camera: CameraSnapshot;
615
+ readonly standardLighting: StandardTopologyInputValue | undefined;
616
+ readonly validated: readonly ValidatedRenderable[];
617
+ readonly dispatch: readonly DispatchEntry[];
618
+ readonly shadowCastersActive: boolean;
619
+ readonly splitLdrSprite: boolean;
620
+ readonly reflectionFallbackAvailable: boolean;
621
+ }): RecoveryPipelineReadiness {
622
+ const requests: RecoveryPipelineRequest[] = [];
623
+ const requestKeys = new Set<string>();
624
+ const sampleCount =
625
+ input.camera.antialias === 'msaa' && input.internals.device.caps.backendKind !== 'wgpu-webgl2'
626
+ ? 4
627
+ : 1;
628
+ const isHdrTarget = input.camera.tonemap !== 'none' || input.reflectionFallbackAvailable;
629
+ addStandardMaterialRequests({
630
+ requests,
631
+ requestKeys,
632
+ internals: input.internals,
633
+ pipelineState: input.pipelineState,
634
+ validated: input.validated,
635
+ standardLighting: input.standardLighting,
636
+ sampleCount,
637
+ isHdrTarget,
638
+ reflectionFallbackAvailable: input.reflectionFallbackAvailable,
639
+ });
640
+ if (input.splitLdrSprite) {
641
+ // The split pass is the non-tonemapped Standard scene target, not the
642
+ // swap-chain storage/view format. StandardForwardLane keeps that target
643
+ // rgba16float on every non-clear linear-LDR path; using the surface format
644
+ // here would prepare a different PipelineSpec from the record seam and
645
+ // force a first-frame PSO miss.
646
+ const colorFormat = 'rgba16float' as GPUTextureFormat;
647
+ addTransparentSpriteRequests({
648
+ requests,
649
+ requestKeys,
650
+ internals: input.internals,
651
+ pipelineState: input.pipelineState,
652
+ validated: input.validated,
653
+ standardLighting: input.standardLighting,
654
+ sampleCount,
655
+ isHdrTarget: isHdrTarget || colorFormat === 'rgba16float',
656
+ colorFormat,
657
+ });
658
+ }
659
+ const hasTriangleGeometry = input.validated.some((entry) =>
660
+ entry.mesh.submeshes.some(
661
+ (submesh) => submesh.topology === 'triangle-list' || submesh.topology === 'triangle-strip',
662
+ ),
663
+ );
664
+ if (input.shadowCastersActive && hasTriangleGeometry) {
665
+ addShadowRequests({
666
+ requests,
667
+ requestKeys,
668
+ internals: input.internals,
669
+ pipelineState: input.pipelineState,
670
+ validated: input.validated,
671
+ dispatch: input.dispatch,
672
+ });
673
+ }
674
+ const assertFirstRecoveryFrame = (): void => {
675
+ for (const request of requests) {
676
+ const first = request.resolve();
677
+ const second = request.resolve();
678
+ if (first === null || second === null || first.pipeline !== second.pipeline) {
679
+ throw new PipelineSpecError({
680
+ code: 'pipeline-build-failed',
681
+ detail: {
682
+ spec: request.spec,
683
+ stablePipeline: first !== null && second !== null && first.pipeline === second.pipeline,
684
+ },
685
+ hint: 'the recovery candidate must resolve every LKG pipeline twice from its prepared cache',
686
+ });
687
+ }
688
+ }
689
+ };
690
+ assertFirstRecoveryFrame();
691
+ return {
692
+ pipelineSpecs: Object.freeze(requests.map((request) => request.spec)),
693
+ assertFirstRecoveryFrame,
694
+ };
695
+ }