@forgeax/engine-render 0.1.21 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (426) hide show
  1. package/README.md +150 -29
  2. package/dist/assembly/backend-contract.d.ts +13 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/device-feature-admission.d.ts.map +1 -1
  5. package/dist/assembly/factory.d.ts +14 -6
  6. package/dist/assembly/factory.d.ts.map +1 -1
  7. package/dist/assembly/host-contract.d.ts +10 -0
  8. package/dist/assembly/host-contract.d.ts.map +1 -1
  9. package/dist/authoring.mjs +1 -1
  10. package/dist/{chunk-PCHBPYML.mjs → chunk-4L3P6DT5.mjs} +2 -2
  11. package/dist/chunk-4L3P6DT5.mjs.map +1 -0
  12. package/dist/{chunk-VFPLTKCU.mjs → chunk-4NPUASZR.mjs} +15 -4
  13. package/dist/chunk-4NPUASZR.mjs.map +1 -0
  14. package/dist/chunk-DIYW3M5D.mjs +5085 -0
  15. package/dist/chunk-DIYW3M5D.mjs.map +1 -0
  16. package/dist/chunk-FBC4R44J.mjs +1003 -0
  17. package/dist/chunk-FBC4R44J.mjs.map +1 -0
  18. package/dist/{chunk-FS2KNUQH.mjs → chunk-FF7K3FSO.mjs} +253 -489
  19. package/dist/chunk-FF7K3FSO.mjs.map +1 -0
  20. package/dist/chunk-HZUPSYW7.mjs +1104 -0
  21. package/dist/chunk-HZUPSYW7.mjs.map +1 -0
  22. package/dist/{chunk-6OPXDQ2E.mjs → chunk-QODA5UKU.mjs} +33 -294
  23. package/dist/chunk-QODA5UKU.mjs.map +1 -0
  24. package/dist/chunk-YALPS44A.mjs +296 -0
  25. package/dist/chunk-YALPS44A.mjs.map +1 -0
  26. package/dist/{chunk-5YADUCA7.mjs → chunk-ZUWKAZ2I.mjs} +585 -991
  27. package/dist/chunk-ZUWKAZ2I.mjs.map +1 -0
  28. package/dist/cluster-binner.d.ts +5 -0
  29. package/dist/cluster-binner.d.ts.map +1 -1
  30. package/dist/components/index.d.ts +3 -0
  31. package/dist/components/index.d.ts.map +1 -1
  32. package/dist/components/light-helpers.d.ts +4 -0
  33. package/dist/components/light-helpers.d.ts.map +1 -1
  34. package/dist/components/light-probe.d.ts +9 -0
  35. package/dist/components/light-probe.d.ts.map +1 -0
  36. package/dist/components/rect-area-light.d.ts +12 -0
  37. package/dist/components/rect-area-light.d.ts.map +1 -0
  38. package/dist/components/scene-instance.d.ts +4 -0
  39. package/dist/components/scene-instance.d.ts.map +1 -1
  40. package/dist/components/spot-light.d.ts +3 -0
  41. package/dist/components/spot-light.d.ts.map +1 -1
  42. package/dist/construct-renderer.mjs +10437 -10044
  43. package/dist/construct-renderer.mjs.map +1 -1
  44. package/dist/device/gpu-residency.d.ts +8 -1
  45. package/dist/device/gpu-residency.d.ts.map +1 -1
  46. package/dist/device/lifecycle-transaction.d.ts +2 -0
  47. package/dist/device/lifecycle-transaction.d.ts.map +1 -0
  48. package/dist/environment/lifecycle.d.ts.map +1 -1
  49. package/dist/errors/gpu-driven.d.ts +26 -0
  50. package/dist/errors/gpu-driven.d.ts.map +1 -0
  51. package/dist/errors/index.d.ts +1 -0
  52. package/dist/errors/index.d.ts.map +1 -1
  53. package/dist/errors/recover.d.ts +9 -1
  54. package/dist/errors/recover.d.ts.map +1 -1
  55. package/dist/errors/render.d.ts +26 -1
  56. package/dist/errors/render.d.ts.map +1 -1
  57. package/dist/extract/gpu-driven.d.ts +50 -0
  58. package/dist/extract/gpu-driven.d.ts.map +1 -0
  59. package/dist/extract/visibility.d.ts.map +1 -1
  60. package/dist/gpu-driven/batch-topology.d.ts +34 -0
  61. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  62. package/dist/gpu-driven/prepared-draw.d.ts +63 -0
  63. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
  64. package/dist/gpu-driven/production-raster.d.ts +98 -2
  65. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  66. package/dist/gpu-driven/view-gpu.d.ts +64 -1
  67. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  68. package/dist/gpu-scene-schema.d.ts +14 -0
  69. package/dist/gpu-scene-schema.d.ts.map +1 -1
  70. package/dist/gpu-scene.d.ts +8 -1
  71. package/dist/gpu-scene.d.ts.map +1 -1
  72. package/dist/gpu-usage.d.ts +0 -1
  73. package/dist/gpu-usage.d.ts.map +1 -1
  74. package/dist/hdrp-buffers.d.ts +3 -3
  75. package/dist/hdrp-buffers.d.ts.map +1 -1
  76. package/dist/index.d.ts +12 -1
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.mjs +90 -5
  79. package/dist/index.mjs.map +1 -1
  80. package/dist/inspection-types.d.ts +163 -1
  81. package/dist/inspection-types.d.ts.map +1 -1
  82. package/dist/internal.d.ts +9 -0
  83. package/dist/internal.d.ts.map +1 -1
  84. package/dist/internal.mjs +23 -2
  85. package/dist/internal.mjs.map +1 -1
  86. package/dist/light-buffer-layout.d.ts +58 -149
  87. package/dist/light-buffer-layout.d.ts.map +1 -1
  88. package/dist/materials.d.ts.map +1 -1
  89. package/dist/pbr-pipeline.d.ts +26 -12
  90. package/dist/pbr-pipeline.d.ts.map +1 -1
  91. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  92. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -1
  93. package/dist/pipeline/standard-lighting/light-frame.d.ts +3 -3
  94. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -1
  95. package/dist/pipeline/standard-lighting/topology.d.ts +1 -1
  96. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -1
  97. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -1
  98. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  99. package/dist/pipeline-builder.d.ts +2 -0
  100. package/dist/pipeline-builder.d.ts.map +1 -1
  101. package/dist/pipeline-spec.d.ts +1 -1
  102. package/dist/pipeline-spec.d.ts.map +1 -1
  103. package/dist/plugin.d.ts.map +1 -1
  104. package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
  105. package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
  106. package/dist/prepare/extended-lighting/resources.d.ts +72 -0
  107. package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
  108. package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
  109. package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
  110. package/dist/prepare/extended-lighting/state.d.ts +24 -0
  111. package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
  112. package/dist/record/frame-lighting.d.ts +8 -6
  113. package/dist/record/frame-lighting.d.ts.map +1 -1
  114. package/dist/record/frame-snapshot.d.ts +50 -10
  115. package/dist/record/frame-snapshot.d.ts.map +1 -1
  116. package/dist/record/frame.d.ts +7 -3
  117. package/dist/record/frame.d.ts.map +1 -1
  118. package/dist/record/gpu-timing.d.ts +19 -7
  119. package/dist/record/gpu-timing.d.ts.map +1 -1
  120. package/dist/record/helpers.d.ts +0 -20
  121. package/dist/record/helpers.d.ts.map +1 -1
  122. package/dist/record/main-pass-geometry.d.ts +6 -1
  123. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  124. package/dist/record/main-pass-material.d.ts +3 -1
  125. package/dist/record/main-pass-material.d.ts.map +1 -1
  126. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  127. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  128. package/dist/record/render-context.d.ts +57 -6
  129. package/dist/record/render-context.d.ts.map +1 -1
  130. package/dist/record/shadow-pass.d.ts.map +1 -1
  131. package/dist/record/typed-frame-graph.d.ts +49 -2
  132. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  133. package/dist/record/view-ubo.d.ts +1 -2
  134. package/dist/record/view-ubo.d.ts.map +1 -1
  135. package/dist/reflection/inspection.d.ts +10 -0
  136. package/dist/reflection/inspection.d.ts.map +1 -0
  137. package/dist/reflection/projection.d.ts +49 -0
  138. package/dist/reflection/projection.d.ts.map +1 -1
  139. package/dist/reflection/record-owner.d.ts +60 -0
  140. package/dist/reflection/record-owner.d.ts.map +1 -0
  141. package/dist/render-contract.d.ts +14 -8
  142. package/dist/render-contract.d.ts.map +1 -1
  143. package/dist/render-pipeline.d.ts +7 -0
  144. package/dist/render-pipeline.d.ts.map +1 -1
  145. package/dist/render-system-extract.d.ts +104 -16
  146. package/dist/render-system-extract.d.ts.map +1 -1
  147. package/dist/render-system.d.ts +12 -1
  148. package/dist/render-system.d.ts.map +1 -1
  149. package/dist/scene/probe-blend-record.d.ts +22 -0
  150. package/dist/scene/probe-blend-record.d.ts.map +1 -0
  151. package/dist/scene/probe-blend.d.ts +142 -0
  152. package/dist/scene/probe-blend.d.ts.map +1 -0
  153. package/dist/scene/render-scene-types.d.ts +0 -6
  154. package/dist/scene/render-scene-types.d.ts.map +1 -1
  155. package/dist/scene/render-scene.d.ts +103 -9
  156. package/dist/scene/render-scene.d.ts.map +1 -1
  157. package/dist/scene/visibility/bounds.d.ts +20 -0
  158. package/dist/scene/visibility/bounds.d.ts.map +1 -0
  159. package/dist/scene/visibility/budget.d.ts +16 -0
  160. package/dist/scene/visibility/budget.d.ts.map +1 -0
  161. package/dist/scene/visibility/facet.d.ts +73 -0
  162. package/dist/scene/visibility/facet.d.ts.map +1 -0
  163. package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
  164. package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
  165. package/dist/scene/visibility/gpu-lod.d.ts +46 -0
  166. package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
  167. package/dist/scene/visibility/inspection.d.ts +132 -0
  168. package/dist/scene/visibility/inspection.d.ts.map +1 -0
  169. package/dist/scene/visibility/lod-selector.d.ts +25 -0
  170. package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
  171. package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
  172. package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
  173. package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
  174. package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
  175. package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
  176. package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
  177. package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
  178. package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
  179. package/dist/scene/visibility/types.d.ts +34 -0
  180. package/dist/scene/visibility/types.d.ts.map +1 -0
  181. package/dist/ssr/admission.d.ts +122 -0
  182. package/dist/ssr/admission.d.ts.map +1 -0
  183. package/dist/ssr/composition.d.ts +32 -0
  184. package/dist/ssr/composition.d.ts.map +1 -0
  185. package/dist/ssr/errors.d.ts +39 -0
  186. package/dist/ssr/errors.d.ts.map +1 -0
  187. package/dist/ssr/identity.d.ts +13 -0
  188. package/dist/ssr/identity.d.ts.map +1 -0
  189. package/dist/systems/skin-palette-allocator.d.ts +1 -1
  190. package/dist/temporal/frame-coordinator.d.ts +13 -0
  191. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  192. package/dist/temporal/frame.d.ts +2 -0
  193. package/dist/temporal/frame.d.ts.map +1 -1
  194. package/dist/temporal/index.mjs +6 -5
  195. package/dist/temporal/view.d.ts +7 -0
  196. package/dist/temporal/view.d.ts.map +1 -1
  197. package/dist/tilemap-chunk-extract-system.d.ts +1 -1
  198. package/dist/typed-render-graph-primitives.d.ts +4 -0
  199. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  200. package/dist/volume/passes.d.ts +8 -4
  201. package/dist/volume/passes.d.ts.map +1 -1
  202. package/package.json +20 -20
  203. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +5 -0
  204. package/src/__tests__/detached-inspection.integration.test.ts +6 -0
  205. package/src/__tests__/device-feature-admission.unit.test.ts +13 -1
  206. package/src/__tests__/direct-light-snapshot.unit.test.ts +59 -3
  207. package/src/__tests__/environment-generation.integration.test.ts +16 -0
  208. package/src/__tests__/evidence-identity.ts +13 -0
  209. package/src/__tests__/evidence-identity.unit.test.ts +24 -0
  210. package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
  211. package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
  212. package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
  213. package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
  214. package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
  215. package/src/__tests__/factory-contract.integration.test.ts +33 -0
  216. package/src/__tests__/frame-observation.contract.test.ts +15 -0
  217. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
  218. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +1 -0
  219. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +1 -0
  220. package/src/__tests__/gpu-driven-production.integration.test.ts +572 -9
  221. package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
  222. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
  223. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +89 -2
  224. package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
  225. package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
  226. package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
  227. package/src/__tests__/gpu-lod-evidence.ts +188 -0
  228. package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
  229. package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
  230. package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
  231. package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
  232. package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
  233. package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
  234. package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
  235. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
  236. package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
  237. package/src/__tests__/gpu-scene.unit.test.ts +49 -3
  238. package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
  239. package/src/__tests__/light-inspection.unit.test.ts +55 -0
  240. package/src/__tests__/light-resource-error.unit.test.ts +43 -0
  241. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
  242. package/src/__tests__/lod-bounds.unit.test.ts +42 -0
  243. package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
  244. package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
  245. package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
  246. package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
  247. package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
  248. package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
  249. package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
  250. package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
  251. package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
  252. package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
  253. package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
  254. package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
  255. package/src/__tests__/lod-selector.profile.test.ts +35 -0
  256. package/src/__tests__/lod-selector.unit.test.ts +68 -0
  257. package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
  258. package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
  259. package/src/__tests__/ltc-resources.unit.test.ts +32 -0
  260. package/src/__tests__/material-contract-inventory.unit.test.ts +17 -0
  261. package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
  262. package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
  263. package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
  264. package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
  265. package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
  266. package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
  267. package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
  268. package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
  269. package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
  270. package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
  271. package/src/__tests__/occlusion-query.evidence.ts +178 -0
  272. package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
  273. package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
  274. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
  275. package/src/__tests__/probe-bindings.unit.test.ts +200 -0
  276. package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
  277. package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
  278. package/src/__tests__/probe-capacity.integration.test.ts +97 -0
  279. package/src/__tests__/probe-recovery.integration.test.ts +104 -0
  280. package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
  281. package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
  282. package/src/__tests__/profiler-phase-token.test.ts +1 -0
  283. package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
  284. package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
  285. package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
  286. package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
  287. package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
  288. package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
  289. package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
  290. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
  291. package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
  292. package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
  293. package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
  294. package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
  295. package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
  296. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +76 -0
  297. package/src/__tests__/skin-motion-regression.unit.test.ts +22 -0
  298. package/src/__tests__/skinned-shadow-caster.test.ts +2 -2
  299. package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
  300. package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
  301. package/src/__tests__/ssr-composition.unit.test.ts +46 -0
  302. package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
  303. package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
  304. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +67 -0
  305. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +7 -0
  306. package/src/__tests__/standard-lighting-inspection.integration.test.ts +1 -1
  307. package/src/__tests__/standard-lighting-write.unit.test.ts +66 -2
  308. package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
  309. package/src/__tests__/temporal-view.unit.test.ts +3 -3
  310. package/src/__tests__/transmission-prewarm.unit.test.ts +69 -0
  311. package/src/__tests__/visibility-budget.integration.test.ts +140 -0
  312. package/src/__tests__/visibility-budget.unit.test.ts +70 -0
  313. package/src/__tests__/visibility-extract.integration.test.ts +11 -6
  314. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
  315. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
  316. package/src/assembly/backend-contract.ts +13 -0
  317. package/src/assembly/device-feature-admission.ts +16 -9
  318. package/src/assembly/factory.ts +547 -93
  319. package/src/assembly/host-contract.ts +10 -0
  320. package/src/cluster-binner.ts +31 -0
  321. package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
  322. package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
  323. package/src/components/index.ts +3 -0
  324. package/src/components/light-helpers.ts +52 -1
  325. package/src/components/light-probe.ts +13 -0
  326. package/src/components/rect-area-light.ts +15 -0
  327. package/src/components/scene-instance.ts +6 -0
  328. package/src/components/spot-light.ts +3 -0
  329. package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
  330. package/src/device/gpu-residency.ts +140 -9
  331. package/src/device/lifecycle-transaction.ts +12 -0
  332. package/src/environment/lifecycle.ts +8 -1
  333. package/src/errors/gpu-driven.ts +92 -0
  334. package/src/errors/index.ts +1 -0
  335. package/src/errors/recover.ts +32 -0
  336. package/src/errors/render.ts +55 -1
  337. package/src/extract/camera.ts +3 -3
  338. package/src/extract/gpu-driven.ts +108 -0
  339. package/src/extract/visibility.ts +0 -23
  340. package/src/gpu-driven/batch-topology.ts +206 -28
  341. package/src/gpu-driven/prepared-draw.ts +208 -0
  342. package/src/gpu-driven/production-raster.ts +953 -41
  343. package/src/gpu-driven/view-gpu.ts +411 -29
  344. package/src/gpu-scene-schema.ts +13 -0
  345. package/src/gpu-scene.ts +134 -65
  346. package/src/gpu-usage.ts +0 -1
  347. package/src/hdrp-buffers.ts +6 -6
  348. package/src/index.ts +74 -0
  349. package/src/inspection-types.ts +220 -1
  350. package/src/internal.ts +38 -0
  351. package/src/light-buffer-layout.ts +154 -324
  352. package/src/materials.ts +16 -2
  353. package/src/pbr-pipeline.ts +151 -45
  354. package/src/pipeline/standard-forward-lane.ts +47 -0
  355. package/src/pipeline/standard-lighting/graph.ts +2 -1
  356. package/src/pipeline/standard-lighting/light-frame.ts +3 -2
  357. package/src/pipeline/standard-lighting/topology.ts +1 -1
  358. package/src/pipeline/standard-lighting/transport.ts +2 -1
  359. package/src/pipeline/standard-pipeline.ts +2 -0
  360. package/src/pipeline-builder.ts +5 -2
  361. package/src/pipeline-spec.ts +12 -1
  362. package/src/plugin.ts +4 -0
  363. package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
  364. package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
  365. package/src/prepare/extended-lighting/resources.ts +389 -0
  366. package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
  367. package/src/prepare/extended-lighting/state.ts +92 -0
  368. package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
  369. package/src/record/__tests__/temporal-payload.unit.test.ts +23 -1
  370. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
  371. package/src/record/frame-lighting.ts +252 -53
  372. package/src/record/frame-snapshot.ts +57 -12
  373. package/src/record/frame.ts +410 -93
  374. package/src/record/gpu-timing.ts +108 -44
  375. package/src/record/helpers.ts +0 -58
  376. package/src/record/main-pass-geometry.ts +204 -39
  377. package/src/record/main-pass-material.ts +8 -1
  378. package/src/record/main-pass-sprite-draws.ts +52 -85
  379. package/src/record/mesh-ssbo.ts +47 -36
  380. package/src/record/render-context.ts +65 -4
  381. package/src/record/shadow-pass.ts +66 -40
  382. package/src/record/typed-frame-graph.ts +225 -83
  383. package/src/record/view-ubo.ts +14 -24
  384. package/src/reflection/inspection.ts +67 -0
  385. package/src/reflection/projection.ts +196 -1
  386. package/src/reflection/record-owner.ts +1283 -0
  387. package/src/render-contract.ts +17 -5
  388. package/src/render-pipeline.ts +5 -0
  389. package/src/render-system-extract.ts +493 -134
  390. package/src/render-system.ts +811 -615
  391. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
  392. package/src/scene/probe-blend-record.ts +54 -0
  393. package/src/scene/probe-blend.ts +813 -0
  394. package/src/scene/render-scene-types.ts +0 -7
  395. package/src/scene/render-scene.ts +848 -183
  396. package/src/scene/visibility/bounds.ts +57 -0
  397. package/src/scene/visibility/budget.ts +40 -0
  398. package/src/scene/visibility/facet.ts +400 -0
  399. package/src/scene/visibility/gpu-frame-timing.ts +101 -0
  400. package/src/scene/visibility/gpu-lod.ts +119 -0
  401. package/src/scene/visibility/inspection.ts +313 -0
  402. package/src/scene/visibility/lod-selector.ts +84 -0
  403. package/src/scene/visibility/occlusion-confidence.ts +478 -0
  404. package/src/scene/visibility/occlusion-pass.ts +165 -0
  405. package/src/scene/visibility/occlusion-query-pool.ts +178 -0
  406. package/src/scene/visibility/occlusion-runtime.ts +672 -0
  407. package/src/scene/visibility/types.ts +50 -0
  408. package/src/ssr/admission.ts +451 -0
  409. package/src/ssr/composition.ts +73 -0
  410. package/src/ssr/errors.ts +76 -0
  411. package/src/ssr/identity.ts +12 -0
  412. package/src/systems/skin-palette-allocator.ts +1 -1
  413. package/src/temporal/frame-coordinator.ts +26 -0
  414. package/src/temporal/frame.ts +14 -1
  415. package/src/temporal/view.ts +11 -0
  416. package/src/tilemap-chunk-extract-system.ts +4 -4
  417. package/src/typed-render-graph-primitives.ts +48 -0
  418. package/src/volume/passes.ts +46 -49
  419. package/dist/.tsbuildinfo +0 -1
  420. package/dist/chunk-5YADUCA7.mjs.map +0 -1
  421. package/dist/chunk-6OPXDQ2E.mjs.map +0 -1
  422. package/dist/chunk-BXBQQKFQ.mjs +0 -67
  423. package/dist/chunk-BXBQQKFQ.mjs.map +0 -1
  424. package/dist/chunk-FS2KNUQH.mjs.map +0 -1
  425. package/dist/chunk-PCHBPYML.mjs.map +0 -1
  426. package/dist/chunk-VFPLTKCU.mjs.map +0 -1
@@ -62,6 +62,7 @@ import type {
62
62
  } from '../render-pipeline';
63
63
  import type { ExtractedLights, ExtractedVolumetricFog } from '../render-system-extract';
64
64
  import { SHADOW_ATLAS_DEFAULT_FACE_SIZE, SHADOW_ATLAS_DEFAULT_LAYERS } from '../shadow-atlas';
65
+ import type { SsrAdmissionResult } from '../ssr/admission';
65
66
  import type { RenderTarget } from '../targets/contracts';
66
67
  import type { RenderTargetPhysical } from '../targets/physical';
67
68
  import {
@@ -82,7 +83,7 @@ import { buildPerFrameBindGroups } from './frame-lighting';
82
83
  import { getTextureIdentity, type RenderFrameState } from './frame-snapshot';
83
84
  import type { GpuPassTimingPassIdentity } from './gpu-pass-timing/contract.js';
84
85
  import type { GpuPassTimingCapture, GpuPassTimingSession } from './gpu-pass-timing/session.js';
85
- import type { GpuTimingCapture, VolumeTimingTimestampWrites } from './gpu-timing';
86
+ import type { GpuTimingCapture } from './gpu-timing';
86
87
  import { encodeMainPass } from './main-pass';
87
88
  import type {
88
89
  _InternalRenderPipelineContext,
@@ -104,6 +105,97 @@ export interface TemporalGraphRoster {
104
105
  readonly uploads: number;
105
106
  }
106
107
 
108
+ export interface ReflectionFallbackGraphRoster {
109
+ readonly enabled: boolean;
110
+ readonly attachments: readonly string[];
111
+ readonly passes: readonly string[];
112
+ readonly bindings: readonly string[];
113
+ readonly historyCount: 0;
114
+ readonly temporalDemand: 0;
115
+ }
116
+
117
+ export interface ReflectionFallbackGraphCandidate {
118
+ readonly generation: number;
119
+ readonly source: 'probe' | 'skylight' | 'neutral';
120
+ readonly roster: ReflectionFallbackGraphRoster;
121
+ }
122
+
123
+ export interface SsrAdmissionGraphRoster {
124
+ readonly enabled: boolean;
125
+ readonly attachments: readonly string[];
126
+ readonly passes: readonly string[];
127
+ readonly bindings: readonly string[];
128
+ readonly historyCount: 0;
129
+ readonly temporalDemand: 0;
130
+ }
131
+
132
+ /**
133
+ * Admission is the sole switch for parent SSR graph work. A blocked result
134
+ * projects to an empty roster, so missing receipts cannot allocate or bind
135
+ * any SSR resource.
136
+ */
137
+ export function createSsrAdmissionGraphRoster(
138
+ admission: Pick<SsrAdmissionResult, 'status'>,
139
+ ): SsrAdmissionGraphRoster {
140
+ if (admission.status !== 'admitted') {
141
+ return {
142
+ enabled: false,
143
+ attachments: [],
144
+ passes: [],
145
+ bindings: [],
146
+ historyCount: 0,
147
+ temporalDemand: 0,
148
+ };
149
+ }
150
+ return {
151
+ enabled: true,
152
+ attachments: ['ssr-reflection-admission'],
153
+ passes: ['ssr-m0-admission'],
154
+ bindings: ['ssr-reflection-admission'],
155
+ historyCount: 0,
156
+ temporalDemand: 0,
157
+ };
158
+ }
159
+
160
+ export type ReflectionFallbackGraphFailure = 'compile-failed' | 'encode-failed' | 'submit-failed';
161
+
162
+ export function createReflectionFallbackGraphRoster(input: {
163
+ readonly fallbackDemand: boolean;
164
+ }): ReflectionFallbackGraphRoster {
165
+ if (!input.fallbackDemand) {
166
+ return {
167
+ enabled: false,
168
+ attachments: [],
169
+ passes: [],
170
+ bindings: [],
171
+ historyCount: 0,
172
+ temporalDemand: 0,
173
+ };
174
+ }
175
+ return {
176
+ enabled: true,
177
+ attachments: ['reflection-fallback-linear-hdr'],
178
+ passes: ['standard-main'],
179
+ bindings: ['reflection-fallback-output'],
180
+ historyCount: 0,
181
+ temporalDemand: 0,
182
+ };
183
+ }
184
+
185
+ export function commitReflectionFallbackGraph(
186
+ candidate: ReflectionFallbackGraphCandidate,
187
+ result:
188
+ | { readonly ok: true }
189
+ | { readonly ok: false; readonly reason: ReflectionFallbackGraphFailure },
190
+ ): {
191
+ readonly visible: boolean;
192
+ readonly generation: number;
193
+ readonly source?: ReflectionFallbackGraphCandidate['source'];
194
+ } {
195
+ if (!result.ok || !candidate.roster.enabled) return { visible: false, generation: 0 };
196
+ return { visible: true, generation: candidate.generation, source: candidate.source };
197
+ }
198
+
107
199
  function importTemporalHistoryTarget(
108
200
  graph: RenderGraphBuilder<RenderPipelineFrame>,
109
201
  label: string,
@@ -730,16 +822,6 @@ const timingInstrumentationStates = new WeakMap<
730
822
  TimingInstrumentationState
731
823
  >();
732
824
 
733
- interface VolumeTimingInstrumentationState {
734
- readonly instrumentation: RenderGraphPassInstrumentation<RenderPipelineFrame>;
735
- setCapture(capture: GpuTimingCapture | undefined): void;
736
- }
737
-
738
- const volumeTimingInstrumentationStates = new WeakMap<
739
- RenderSystemInternals,
740
- VolumeTimingInstrumentationState
741
- >();
742
-
743
825
  type CompiledGraphTargetAccess = CompiledRenderGraph<RenderPipelineFrame> & {
744
826
  readonly getColorTargetDescriptor: (
745
827
  name: string,
@@ -930,6 +1012,7 @@ function topologyOf(
930
1012
  standardProfile: internals.standardProfile,
931
1013
  config,
932
1014
  clearOnly,
1015
+ reflectionFallback: { enabled: frameState.reflectionFallbackDemand === true },
933
1016
  surface: {
934
1017
  width,
935
1018
  height,
@@ -1262,6 +1345,7 @@ export function ensureCompiledFrameGraph(
1262
1345
  cubeCaptureState?: CubeCaptureGraphState,
1263
1346
  clearOnly = false,
1264
1347
  transmissionDemand?: TransmissionDemand,
1348
+ occlusion?: import('../scene/visibility/occlusion-runtime').OcclusionFrameProjection,
1265
1349
  volumetricFog?: ExtractedVolumetricFog,
1266
1350
  volumeTopologyCandidate = false,
1267
1351
  standardLighting?: StandardTopologyInputValue,
@@ -1354,6 +1438,17 @@ export function ensureCompiledFrameGraph(
1354
1438
  : topologyResult.value;
1355
1439
  const key = JSON.stringify({
1356
1440
  topology,
1441
+ // GPU-driven residency can become available after the first record pass
1442
+ // (custom mesh handles are resolved into the per-frame projection). The
1443
+ // topology signature alone is intentionally stable across that lifecycle,
1444
+ // so include the prepared projection's presence to invalidate a cached
1445
+ // CPU-only graph when the GPU owner becomes ready, and vice versa.
1446
+ gpuDrivenProjectionActive: gpuDriven !== undefined,
1447
+ // Query reservations are frame-local transport state. The projection is
1448
+ // renderer-owned and read dynamically by the compiled pass, so a page
1449
+ // rotation must not invalidate the graph or its cached bind groups.
1450
+ occlusionQuery:
1451
+ occlusion === undefined ? undefined : { active: true, sampleCount: occlusion.sampleCount },
1357
1452
  cubeCaptureSlots: cubeCaptureState?.work.length ?? 0,
1358
1453
  reflectionProbeSlots: cubeCaptureState?.reflectionProbes?.work.map((work) => [
1359
1454
  work.probeIndex,
@@ -1385,6 +1480,7 @@ export function ensureCompiledFrameGraph(
1385
1480
  graph: builder,
1386
1481
  ...(standardLighting === undefined ? {} : { standardLighting }),
1387
1482
  capabilities: { rgba16floatRenderable: internals.device.caps.rgba16floatRenderable },
1483
+ ...(occlusion === undefined ? {} : { occlusion }),
1388
1484
  ...(taaHistory === undefined ? {} : { taaHistory }),
1389
1485
  encodeTransmissionMip: ({ pass, resources, source }) => {
1390
1486
  const sourceView = resources.textureView(source);
@@ -1472,6 +1568,11 @@ export function executeCompiledFrameGraph(
1472
1568
  frame: RenderPipelineFrame,
1473
1569
  encoder: RhiCommandEncoder,
1474
1570
  runPass?: import('@forgeax/engine-render-graph').RenderGraphPassRunner,
1571
+ frameHooks?: {
1572
+ readonly afterGraphExecute?: () => Result<void, RhiError>;
1573
+ readonly onSubmitted?: () => void;
1574
+ readonly onAborted?: () => void;
1575
+ },
1475
1576
  readbackFaces?: readonly number[],
1476
1577
  onSubmitted?: (completed: Promise<unknown>) => void,
1477
1578
  timingCapture?: GpuTimingCapture,
@@ -1494,6 +1595,8 @@ export function executeCompiledFrameGraph(
1494
1595
  rejectTemporalFrame();
1495
1596
  return false;
1496
1597
  }
1598
+ const legacyTimingInstrumentation =
1599
+ timingCapture === undefined ? undefined : createTimingInstrumentation(timingCapture);
1497
1600
  const timingHost = internals as RenderSystemInternals & {
1498
1601
  gpuPassTimingSession?: GpuPassTimingSession | undefined;
1499
1602
  gpuPassTimingCapture?: GpuPassTimingCapture | undefined;
@@ -1525,19 +1628,31 @@ export function executeCompiledFrameGraph(
1525
1628
  ? getTimingInstrumentationState(internals, passTimingCapture)
1526
1629
  : timingCapture === undefined
1527
1630
  ? undefined
1528
- : getVolumeTimingInstrumentationState(internals, timingCapture);
1631
+ : undefined;
1632
+ const graphInstrumentation =
1633
+ passTimingCapture !== undefined
1634
+ ? timingInstrumentationState?.instrumentation
1635
+ : legacyTimingInstrumentation;
1529
1636
  type PreparedCommand = { readonly command: CommandBuffer };
1530
1637
  let preparedCommand: PreparedCommand = { command: undefined as never };
1531
1638
  const transaction = executeRendererFrameTransaction<PreparedCommand>({
1532
1639
  build: () => ({ ok: true, value: { command: undefined as never } }),
1533
1640
  execute: () => {
1534
- const executed = graph.execute(frame, runPass, timingInstrumentationState?.instrumentation);
1641
+ const executed = graph.execute(frame, runPass, graphInstrumentation);
1535
1642
  timingInstrumentationState?.setCapture(undefined);
1536
1643
  if (!executed.ok) {
1537
1644
  passTimingCapture?.abort({ code: executed.error.code });
1538
1645
  internals.errorRegistry.fire(executed.error);
1539
1646
  return { ok: false, stage: 'execute' };
1540
1647
  }
1648
+ const afterGraphExecute = frameHooks?.afterGraphExecute;
1649
+ if (afterGraphExecute !== undefined) {
1650
+ const recorded = afterGraphExecute();
1651
+ if (!recorded.ok) {
1652
+ internals.errorRegistry.fire(recorded.error);
1653
+ return { ok: false, stage: 'execute' };
1654
+ }
1655
+ }
1541
1656
  return { ok: true, value: undefined };
1542
1657
  },
1543
1658
  finish: () => {
@@ -1664,6 +1779,43 @@ export function executeCompiledFrameGraph(
1664
1779
  );
1665
1780
  }
1666
1781
  }
1782
+ const fallbackReadback = frameState.reflectionFallbackReadback;
1783
+ frameState.reflectionFallbackReadback = undefined;
1784
+ if (fallbackReadback !== undefined) {
1785
+ const graphAccess = frameState.perFrameGraph;
1786
+ const graphTexture = graphAccess?.getColorTargetTexture(fallbackReadback.name);
1787
+ const descriptor = graphAccess?.getColorTargetDescriptor(fallbackReadback.name);
1788
+ const matches =
1789
+ graphAccess !== undefined &&
1790
+ graphAccess !== null &&
1791
+ graphTexture !== undefined &&
1792
+ descriptor !== undefined &&
1793
+ descriptor.format === fallbackReadback.expected.format &&
1794
+ descriptor.size.width === fallbackReadback.expected.width &&
1795
+ descriptor.size.height === fallbackReadback.expected.height &&
1796
+ descriptor.sample === 1 &&
1797
+ (descriptor.usage & fallbackReadback.expected.usage) ===
1798
+ fallbackReadback.expected.usage &&
1799
+ graphAccess.graphGeneration === fallbackReadback.expected.graphGeneration &&
1800
+ frameState.frameNumber === fallbackReadback.expected.frameId &&
1801
+ getTextureIdentity(graphTexture) === fallbackReadback.expected.textureIdentity;
1802
+ if (matches && graphTexture !== undefined) {
1803
+ encoder.copyTextureToBuffer(
1804
+ { texture: graphTexture },
1805
+ {
1806
+ buffer: fallbackReadback.buffer,
1807
+ bytesPerRow: fallbackReadback.bytesPerRow,
1808
+ rowsPerImage: fallbackReadback.height,
1809
+ },
1810
+ {
1811
+ width: fallbackReadback.width,
1812
+ height: fallbackReadback.height,
1813
+ depthOrArrayLayers: 1,
1814
+ },
1815
+ );
1816
+ fallbackReadback.encoded = true;
1817
+ }
1818
+ }
1667
1819
  internals.encodeRenderTargetReadbacks?.(encoder, readbackFaces);
1668
1820
  const stagedGpuState = frameState.temporalGpuState;
1669
1821
  if (stagedGpuState !== undefined && !hasPendingTemporalGpuSubmit(stagedGpuState)) {
@@ -1696,6 +1848,13 @@ export function executeCompiledFrameGraph(
1696
1848
  return { ok: true, value: undefined };
1697
1849
  },
1698
1850
  submit: () => {
1851
+ const injectedFailure = internals.beforeSubmit?.(internals.device);
1852
+ if (injectedFailure !== undefined) {
1853
+ passTimingCapture?.abort({ code: injectedFailure.code });
1854
+ timingCapture?.discard();
1855
+ internals.errorRegistry.fire(injectedFailure);
1856
+ return { ok: false, stage: 'submit' };
1857
+ }
1699
1858
  const submitted = internals.device.queue.submit([preparedCommand.command]);
1700
1859
  if (!submitted.ok) {
1701
1860
  passTimingCapture?.abort({ code: submitted.error.code });
@@ -1707,6 +1866,23 @@ export function executeCompiledFrameGraph(
1707
1866
  return { ok: true, value: undefined };
1708
1867
  },
1709
1868
  commit: () => {
1869
+ frameHooks?.onSubmitted?.();
1870
+ if (frameState.temporalFrameInput !== undefined) {
1871
+ const temporal = frameState.temporalFrameTransaction.commit({ accepted: true });
1872
+ if (temporal.ok) {
1873
+ frameState.temporalFrame = temporal.value;
1874
+ } else {
1875
+ internals.errorRegistry.fire(
1876
+ new RhiError({
1877
+ code: 'webgpu-runtime-error',
1878
+ expected: 'the staged temporal frame to commit after queue submission',
1879
+ hint: 'discard the temporal candidate and retry the next frame',
1880
+ detail: { error: temporal.error },
1881
+ }),
1882
+ );
1883
+ }
1884
+ frameState.temporalFrameInput = undefined;
1885
+ }
1710
1886
  if (passTimingCapture !== undefined) {
1711
1887
  const completion = internals.device.queue.onSubmittedWorkDone();
1712
1888
  timingHost.gpuPassTimingSubmittedWork = completion;
@@ -1783,6 +1959,7 @@ export function executeCompiledFrameGraph(
1783
1959
  onSubmitted?.(internals.device.queue.onSubmittedWorkDone());
1784
1960
  },
1785
1961
  abort: (failure) => {
1962
+ frameHooks?.onAborted?.();
1786
1963
  passTimingCapture?.abort({ code: failure.stage });
1787
1964
  timingHost.gpuPassTimingCapture = undefined;
1788
1965
  timingHost.gpuPassTimingSubmittedWork = undefined;
@@ -1814,6 +1991,41 @@ export function executeCompiledFrameGraph(
1814
1991
  return transaction.ok;
1815
1992
  }
1816
1993
 
1994
+ function createTimingInstrumentation(
1995
+ capture: GpuTimingCapture,
1996
+ ): RenderGraphPassInstrumentation<RenderPipelineFrame> {
1997
+ return {
1998
+ begin: (pass): RenderGraphPassInstrumentationScope | undefined => {
1999
+ // WebGPU has no portable timestamp boundary for a copy pass. Do not
2000
+ // pretend a command-encoder marker exists; frame timing remains valid
2001
+ // when at least one raster/compute pass is present.
2002
+ if (pass.kind === 'copy') return undefined;
2003
+ const writes = capture.beginPass(pass.name, pass.kind, pass.executionIndex);
2004
+ if (writes === undefined) return undefined;
2005
+ if (pass.kind === 'raster') {
2006
+ return {
2007
+ renderPassDescriptor: (descriptor) => {
2008
+ if (descriptor.timestampWrites !== undefined) {
2009
+ capture.markOwnerConflict(pass.name);
2010
+ return descriptor;
2011
+ }
2012
+ return { ...descriptor, timestampWrites: writes };
2013
+ },
2014
+ };
2015
+ }
2016
+ return {
2017
+ computePassDescriptor: (descriptor) => {
2018
+ if (descriptor.timestampWrites !== undefined) {
2019
+ capture.markOwnerConflict(pass.name);
2020
+ return descriptor;
2021
+ }
2022
+ return { ...descriptor, timestampWrites: writes };
2023
+ },
2024
+ };
2025
+ },
2026
+ };
2027
+ }
2028
+
1817
2029
  function getTimingInstrumentationState(
1818
2030
  internals: RenderSystemInternals,
1819
2031
  capture: GpuPassTimingCapture,
@@ -1912,73 +2124,3 @@ function getTimingInstrumentationState(
1912
2124
  timingInstrumentationStates.set(internals, state);
1913
2125
  return state;
1914
2126
  }
1915
-
1916
- function getVolumeTimingInstrumentationState(
1917
- internals: RenderSystemInternals,
1918
- capture: GpuTimingCapture,
1919
- ): VolumeTimingInstrumentationState {
1920
- const existing = volumeTimingInstrumentationStates.get(internals);
1921
- if (existing !== undefined) {
1922
- existing.setCapture(capture);
1923
- return existing;
1924
- }
1925
- let activeCapture: GpuTimingCapture | undefined = capture;
1926
- let activePassName: string | undefined;
1927
- let activeWrites: VolumeTimingTimestampWrites | undefined;
1928
- const rasterScope: RenderGraphPassInstrumentationScope = {
1929
- renderPassDescriptor: (descriptor) => {
1930
- const currentCapture = activeCapture;
1931
- const passName = activePassName;
1932
- const writes = activeWrites;
1933
- if (currentCapture === undefined || passName === undefined || writes === undefined) {
1934
- return descriptor;
1935
- }
1936
- if (descriptor.timestampWrites !== undefined) {
1937
- currentCapture.skipPass(passName);
1938
- activeWrites = undefined;
1939
- return descriptor;
1940
- }
1941
- return { ...descriptor, timestampWrites: writes };
1942
- },
1943
- };
1944
- const computeScope: RenderGraphPassInstrumentationScope = {
1945
- computePassDescriptor: (descriptor) => {
1946
- const currentCapture = activeCapture;
1947
- const passName = activePassName;
1948
- const writes = activeWrites;
1949
- if (currentCapture === undefined || passName === undefined || writes === undefined) {
1950
- return descriptor;
1951
- }
1952
- if (descriptor.timestampWrites !== undefined) {
1953
- currentCapture.skipPass(passName);
1954
- activeWrites = undefined;
1955
- return descriptor;
1956
- }
1957
- return { ...descriptor, timestampWrites: writes };
1958
- },
1959
- };
1960
- const instrumentation: RenderGraphPassInstrumentation<RenderPipelineFrame> = {
1961
- begin: (pass) => {
1962
- const currentCapture = activeCapture;
1963
- if (currentCapture === undefined) return undefined;
1964
- activePassName = pass.name;
1965
- activeWrites = currentCapture.recordPass(pass.name);
1966
- if (activeWrites === undefined) return undefined;
1967
- if (pass.kind === 'raster') return rasterScope;
1968
- if (pass.kind === 'compute') return computeScope;
1969
- currentCapture.skipPass(pass.name);
1970
- activeWrites = undefined;
1971
- return undefined;
1972
- },
1973
- };
1974
- const state: VolumeTimingInstrumentationState = {
1975
- instrumentation,
1976
- setCapture: (nextCapture) => {
1977
- activeCapture = nextCapture;
1978
- activePassName = undefined;
1979
- activeWrites = undefined;
1980
- },
1981
- };
1982
- volumeTimingInstrumentationStates.set(internals, state);
1983
- return state;
1984
- }
@@ -9,7 +9,6 @@
9
9
  import { mat4 } from '@forgeax/engine-math';
10
10
  import type { Buffer, RhiQueue } from '@forgeax/engine-rhi';
11
11
  import type { DirectionalShadowQuality } from '../components/directional-shadow-filter';
12
- import type { FogFrame } from '../extract/environment';
13
12
  import type { PointsLinesStyle } from '../points-lines/snapshot';
14
13
  import type { CameraSnapshot } from '../render-contract';
15
14
  import type {
@@ -140,18 +139,11 @@ export function writeViewUbo(
140
139
  light: DirectionalLightSnapshot,
141
140
  lights: ExtractedLights,
142
141
  spotShadowSnapshots: readonly SpotLightSnapshot[],
143
- fogOrTemporalOrOffset?: FogFrame | TemporalView | LegacyTemporalView | number,
144
- temporal?: TemporalView,
142
+ temporalOrOffset?: TemporalView | LegacyTemporalView | number,
145
143
  projectorSpotIndex?: number,
146
144
  ): void {
147
- const byteOffset = typeof fogOrTemporalOrOffset === 'number' ? fogOrTemporalOrOffset : 0;
148
- const fogOrTemporal =
149
- typeof fogOrTemporalOrOffset === 'number' ? undefined : fogOrTemporalOrOffset;
150
- const isTemporal =
151
- fogOrTemporal !== undefined &&
152
- ('currentJitterUv' in fogOrTemporal || 'currentUnjitteredViewProjection' in fogOrTemporal);
153
- const fog = isTemporal ? undefined : fogOrTemporal;
154
- const resolvedTemporal = temporal ?? (isTemporal ? fogOrTemporal : undefined);
145
+ const byteOffset = typeof temporalOrOffset === 'number' ? temporalOrOffset : 0;
146
+ const resolvedTemporal = typeof temporalOrOffset === 'number' ? undefined : temporalOrOffset;
155
147
  // Compose worldViewProj once per frame (view * proj).
156
148
  const projMatrix = computeProjectionMatrix(camera);
157
149
  const viewMatrix = computeViewMatrix(camera);
@@ -216,6 +208,16 @@ export function writeViewUbo(
216
208
  viewPayload[228] = camera.near;
217
209
  viewPayload[229] = camera.far;
218
210
  viewPayload[230] = camera.projection === 'orthographic' ? 1 : 0;
211
+ const previousCameraPosition =
212
+ resolvedTemporal !== undefined && 'previousCameraPosition' in resolvedTemporal
213
+ ? resolvedTemporal.previousCameraPosition
214
+ : undefined;
215
+ if (previousCameraPosition !== undefined) {
216
+ viewPayload[232] = previousCameraPosition[0] ?? 0;
217
+ viewPayload[233] = previousCameraPosition[1] ?? 0;
218
+ viewPayload[234] = previousCameraPosition[2] ?? 0;
219
+ viewPayload[235] = 1;
220
+ }
219
221
  // splitPlanes at [108..123] (four vec4 lanes: split/world texel/depth span/reserved).
220
222
  if (lights.splitPlanes !== undefined) {
221
223
  for (let s = 0; s < 4; s++) {
@@ -248,7 +250,7 @@ export function writeViewUbo(
248
250
  // spot index, not by a negative shadow tile: a projector-only spot publishes
249
251
  // its matrix in lane 0 so the shader never samples a zero matrix. Shadowed
250
252
  // projector spots keep their shadow tile lane and carry the projector bit in
251
- // the LightSlot identity word.
253
+ // the DirectLightSlot identity word.
252
254
  // Folded from the former standalone binding 9 UBO to keep the WebGL2
253
255
  // fallback fragment uniform-buffer count <= 11 (GLES 3.0).
254
256
  {
@@ -272,18 +274,6 @@ export function writeViewUbo(
272
274
  }
273
275
  }
274
276
 
275
- // Fog is a resource-owner semantic carried by the shared View ABI. Keep the
276
- // disabled payload zeroed and write only the selected frame facts so both
277
- // direct and clustered lanes consume the same owner projection.
278
- if (fog !== undefined) {
279
- viewPayload[232] = fog.color[0] ?? 0;
280
- viewPayload[233] = fog.color[1] ?? 0;
281
- viewPayload[234] = fog.color[2] ?? 0;
282
- viewPayload[235] = fog.density;
283
- viewPayload[236] = fog.heightFalloff;
284
- viewPayload[237] = fog.maxOpacity;
285
- }
286
-
287
277
  const viewUploadResult = queue.writeBuffer(viewUniformBuffer, byteOffset, viewPayload);
288
278
  if (!viewUploadResult.ok) throw viewUploadResult.error;
289
279
 
@@ -0,0 +1,67 @@
1
+ import type {
2
+ ReflectionFallbackFailureStage,
3
+ ReflectionFallbackInspection,
4
+ ReflectionFallbackReceipt,
5
+ ReflectionFallbackRecoveryAction,
6
+ } from '../inspection-types';
7
+
8
+ export interface ReflectionFallbackFailureInput {
9
+ readonly stage: ReflectionFallbackFailureStage;
10
+ readonly code: string;
11
+ readonly expected: string;
12
+ readonly detail?: Readonly<Record<string, unknown>>;
13
+ }
14
+
15
+ function recoveryFor(
16
+ receipt: ReflectionFallbackReceipt,
17
+ failure?: ReflectionFallbackFailureInput,
18
+ ): ReflectionFallbackRecoveryAction {
19
+ if (failure !== undefined) {
20
+ const code = failure.code.toLowerCase();
21
+ if (code.includes('device') || code.includes('format') || code.includes('capability')) {
22
+ return 'rebuild';
23
+ }
24
+ if (failure.stage === 'prepare' || failure.stage === 'filter') return 'recapture';
25
+ if (failure.stage === 'build' || failure.stage === 'encode') return 'rebuild';
26
+ if (failure.stage === 'finish' || failure.stage === 'submit') return 'retry';
27
+ // Completion failures may still retain a source-identical committed row;
28
+ // use it as LKG, otherwise retry the producer completion.
29
+ if (failure.stage === 'completion') {
30
+ if (receipt.source === 'probe' && (receipt.state === 'active' || receipt.state === 'lkg')) {
31
+ return 'use-LKG';
32
+ }
33
+ if (
34
+ receipt.source === 'skylight' &&
35
+ (receipt.state === 'active' || receipt.state === 'lkg')
36
+ ) {
37
+ return 'use-Skylight';
38
+ }
39
+ if (receipt.source === 'neutral' && receipt.state === 'neutral') return 'use-neutral';
40
+ return 'retry';
41
+ }
42
+ }
43
+ if (receipt.source === 'probe' && (receipt.state === 'active' || receipt.state === 'lkg')) {
44
+ return 'use-LKG';
45
+ }
46
+ if (receipt.source === 'skylight' || receipt.state === 'lkg') return 'use-Skylight';
47
+ return 'use-neutral';
48
+ }
49
+
50
+ /** Projects producer state and the latest closed failure into detached facts. */
51
+ export function inspectReflectionFallback(
52
+ receipt: ReflectionFallbackReceipt,
53
+ failure?: ReflectionFallbackFailureInput,
54
+ ): ReflectionFallbackInspection {
55
+ return {
56
+ receipt,
57
+ recoveryAction: recoveryFor(receipt, failure),
58
+ ...(failure === undefined
59
+ ? {}
60
+ : {
61
+ failureStage: failure.stage,
62
+ failureCode: failure.code,
63
+ expected: failure.expected,
64
+ ...(failure.detail === undefined ? {} : { detail: failure.detail }),
65
+ }),
66
+ };
67
+ }