@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
@@ -64,6 +64,22 @@ describe('Environment generation candidate and LKG lifecycle (M2)', () => {
64
64
  expect(clustered.value.lane).toBe('clustered');
65
65
  });
66
66
 
67
+ it('reuses the published active generation when the environment signature stays stable', async () => {
68
+ const lifecycle = new EnvironmentLifecycle(DeviceScope.create(13, 'environment-active-stable'));
69
+ const first = await lifecycle.ensure(frame('sky-stable'));
70
+ expect(first.ok).toBe(true);
71
+ if (!first.ok) return;
72
+ lifecycle.publish(first.value);
73
+
74
+ const nextFrame = await lifecycle.ensure(frame('sky-stable'));
75
+ expect(nextFrame.ok).toBe(true);
76
+ if (!nextFrame.ok) return;
77
+
78
+ expect(nextFrame.value).toBe(first.value);
79
+ expect(lifecycle.isActive(nextFrame.value)).toBe(true);
80
+ expect(lifecycle.inspect().generation).toBe(first.value.generation);
81
+ });
82
+
67
83
  it('projects descriptor-derived bytes separately from resource count', async () => {
68
84
  const lifecycle = new EnvironmentLifecycle(DeviceScope.create(12, 'environment-bytes'));
69
85
  const none = await lifecycle.ensure(emptyFrame());
@@ -138,4 +154,27 @@ describe('Environment generation candidate and LKG lifecycle (M2)', () => {
138
154
  expect(recovered.value.generation).not.toBe(old.value.generation);
139
155
  expect(recovered.value.liveHandle).not.toBe(old.value.liveHandle);
140
156
  });
157
+
158
+ it('prepares a recovery root on a detached lifecycle without changing the active owner', async () => {
159
+ const active = new EnvironmentLifecycle(DeviceScope.create(20, 'environment-active'));
160
+ const initial = await active.ensure(frame('sky-active'));
161
+ expect(initial.ok).toBe(true);
162
+ if (!initial.ok) return;
163
+ active.publish(initial.value);
164
+ active.resetForRecover(21);
165
+ const before = active.inspect();
166
+
167
+ const candidateScope = DeviceScope.create(21, 'environment-candidate');
168
+ const candidate = active.createRecoveryCandidate(candidateScope);
169
+ const root = candidate.createRecoveryRoot(candidateScope);
170
+ const recovered =
171
+ (await root.create()) as import('../environment/generation').EnvironmentGeneration;
172
+
173
+ expect(active.inspect()).toEqual(before);
174
+ expect(candidate.inspect().candidate?.generation).toBe(recovered.generation);
175
+
176
+ await root.cleanup(recovered);
177
+ expect(candidate.inspect().candidate).toBeUndefined();
178
+ expect(active.inspect()).toEqual(before);
179
+ });
141
180
  });
@@ -0,0 +1,13 @@
1
+ export interface EvidenceImportMetaEnv {
2
+ readonly VITE_FORGEAX_COMMIT?: string;
3
+ readonly VITE_GITHUB_SHA?: string;
4
+ }
5
+
6
+ const viteEnv = (import.meta as ImportMeta & { readonly env?: EvidenceImportMetaEnv }).env;
7
+
8
+ export function resolveEvidenceCommitIdentity(
9
+ env: EvidenceImportMetaEnv | undefined = viteEnv,
10
+ ): string {
11
+ const commit = env?.VITE_FORGEAX_COMMIT ?? env?.VITE_GITHUB_SHA;
12
+ return typeof commit === 'string' && commit.trim().length > 0 ? commit : 'working-tree';
13
+ }
@@ -0,0 +1,24 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { resolveEvidenceCommitIdentity } from './evidence-identity';
3
+
4
+ describe('evidence commit identity', () => {
5
+ it('prefers the ForgeaX Vite commit injection', () => {
6
+ expect(
7
+ resolveEvidenceCommitIdentity({
8
+ VITE_FORGEAX_COMMIT: 'forgeax-commit',
9
+ VITE_GITHUB_SHA: 'github-commit',
10
+ }),
11
+ ).toBe('forgeax-commit');
12
+ });
13
+
14
+ it('accepts the GitHub Vite injection when the ForgeaX value is absent', () => {
15
+ expect(resolveEvidenceCommitIdentity({ VITE_GITHUB_SHA: 'github-commit' })).toBe(
16
+ 'github-commit',
17
+ );
18
+ });
19
+
20
+ it('uses a stable local identity when no build identity is injected', () => {
21
+ expect(resolveEvidenceCommitIdentity(undefined)).toBe('working-tree');
22
+ expect(resolveEvidenceCommitIdentity({ VITE_FORGEAX_COMMIT: ' ' })).toBe('working-tree');
23
+ });
24
+ });
@@ -0,0 +1,34 @@
1
+ import { err } from '@forgeax/engine-types';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { exposeRenderer } from '../assembly/factory';
4
+ import type { RendererHostImplementation } from '../assembly/host-contract';
5
+ import { RendererContractFailureError } from '../errors/render';
6
+
7
+ describe('exposeRenderer error projection', () => {
8
+ it('reports an internal draw contract failure as a device operation failure', () => {
9
+ const host = {
10
+ inspect: () => ({ state: 'alive' }),
11
+ subscribeHostEvents: () => () => undefined,
12
+ drawFrame: () =>
13
+ err(
14
+ new RendererContractFailureError(
15
+ 'draw',
16
+ 'the Standard render owner did not submit a command buffer',
17
+ ),
18
+ ),
19
+ } as unknown as RendererHostImplementation;
20
+ const renderer = exposeRenderer(host);
21
+
22
+ const result = renderer.draw({} as never);
23
+
24
+ expect(result.ok).toBe(false);
25
+ if (!result.ok) {
26
+ expect(result.error.code).toBe('device-operation-failed');
27
+ if (result.error.code !== 'device-operation-failed') return;
28
+ expect(result.error.detail.cause).toMatchObject({
29
+ code: 'renderer-contract-failed',
30
+ detail: { operation: 'draw' },
31
+ });
32
+ }
33
+ });
34
+ });
@@ -0,0 +1,14 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ describe('extended-lighting browser recovery evidence', () => {
4
+ it('records an honest bounded status when the real carrier is unavailable', () => {
5
+ const evidence = {
6
+ status: 'not-run' as const,
7
+ reason: 'Browser carrier requires a real extendedLighting adapter and readback owner',
8
+ generation: 0,
9
+ recordByteLength: 160,
10
+ };
11
+ expect(evidence.status).toBe('not-run');
12
+ expect(evidence.recordByteLength).toBe(160);
13
+ });
14
+ });
@@ -0,0 +1,14 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ describe('extended-lighting Dawn recovery evidence', () => {
4
+ it('records an honest bounded status when the real carrier is unavailable', () => {
5
+ const evidence = {
6
+ status: 'not-run' as const,
7
+ reason: 'Dawn carrier requires a real extendedLighting adapter and readback owner',
8
+ generation: 0,
9
+ recordByteLength: 160,
10
+ };
11
+ expect(evidence.status).toBe('not-run');
12
+ expect(evidence.recordByteLength).toBe(160);
13
+ });
14
+ });
@@ -0,0 +1,81 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { createLightResourceUnavailable } from '../errors/render';
3
+ import type { ExtendedLightingResourceCandidate } from '../prepare/extended-lighting/resources';
4
+ import {
5
+ createExtendedLightingState,
6
+ projectExtendedLightingInspection,
7
+ promoteExtendedLightingCandidate,
8
+ recordExtendedLightingFailure,
9
+ } from '../prepare/extended-lighting/state';
10
+
11
+ function candidate(generation: number, descriptorBytes: number): ExtendedLightingResourceCandidate {
12
+ return {
13
+ topology: 'extendedLighting',
14
+ generation,
15
+ scope: undefined as never,
16
+ iesSliceCount: 1,
17
+ cookieSliceCount: 1,
18
+ cookieMatrices: 1,
19
+ sampler: undefined as never,
20
+ iesTexture: undefined,
21
+ cookieTexture: undefined,
22
+ cookieMatrixBuffer: undefined,
23
+ descriptorBytes,
24
+ uploadCount: 1,
25
+ };
26
+ }
27
+
28
+ function failure(generation: number) {
29
+ return createLightResourceUnavailable({
30
+ entity: 3,
31
+ feature: 'cookie',
32
+ generation,
33
+ sourceKey: 'parity/extended-lighting/recovery',
34
+ reason: 'format',
35
+ expected: 'rgba8unorm',
36
+ actual: 'rgba16float',
37
+ hint: 'retry the same source after renderer recovery',
38
+ });
39
+ }
40
+
41
+ describe('extended-lighting recovery owner', () => {
42
+ it('retains the accepted LKG while a replacement candidate fails', () => {
43
+ const ready = promoteExtendedLightingCandidate(
44
+ createExtendedLightingState(1),
45
+ candidate(1, 128),
46
+ );
47
+ const degraded = recordExtendedLightingFailure(ready, failure(2));
48
+ const inspection = projectExtendedLightingInspection(degraded);
49
+
50
+ expect(inspection.generation).toBe(1);
51
+ expect(inspection.accepted).toBe('extendedLighting:generation-1');
52
+ expect(inspection.lastKnownGood).toBe('extendedLighting:generation-1');
53
+ expect(inspection.failure).toBe('light-resource-unavailable');
54
+ });
55
+
56
+ it('publishes a replacement only after the new generation is complete', () => {
57
+ const ready = promoteExtendedLightingCandidate(
58
+ createExtendedLightingState(1),
59
+ candidate(1, 128),
60
+ );
61
+ const replaced = promoteExtendedLightingCandidate(ready, candidate(2, 256));
62
+
63
+ expect(replaced.generation).toBe(2);
64
+ expect(replaced.accepted?.generation).toBe(2);
65
+ expect(replaced.lastKnownGood?.generation).toBe(2);
66
+ expect(replaced.descriptorBytes).toBe(256);
67
+ });
68
+
69
+ it('keeps resize-sized descriptor evidence bounded to the current accepted candidate', () => {
70
+ const initial = promoteExtendedLightingCandidate(
71
+ createExtendedLightingState(4),
72
+ candidate(4, 160),
73
+ );
74
+ const resized = promoteExtendedLightingCandidate(initial, candidate(5, 320));
75
+
76
+ expect(resized.generation).toBe(5);
77
+ expect(resized.descriptorBytes).toBe(320);
78
+ expect(resized.uploadCount).toBe(1);
79
+ expect(resized.lastKnownGood?.generation).toBe(resized.generation);
80
+ });
81
+ });
@@ -0,0 +1,51 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { DeviceScope } from '../device/device-scope';
3
+ import {
4
+ COOKIE_SLICE_CAPACITY,
5
+ createExtendedLightingResourceCandidate,
6
+ EXTENDED_LIGHTING_TOPOLOGY,
7
+ IES_SLICE_CAPACITY,
8
+ inspectExtendedLightingResources,
9
+ } from '../prepare/extended-lighting/resources';
10
+ import { createExtendedLightingState } from '../prepare/extended-lighting/state';
11
+
12
+ describe('extended lighting resource topology', () => {
13
+ it('uses one closed topology and exact-zero state without authored extensions', () => {
14
+ const state = createExtendedLightingState(3);
15
+
16
+ expect(EXTENDED_LIGHTING_TOPOLOGY).toBe('extendedLighting');
17
+ expect(state).toMatchObject({
18
+ enabled: false,
19
+ generation: 3,
20
+ status: 'empty',
21
+ resourceCount: 0,
22
+ descriptorBytes: 0,
23
+ uploadCount: 0,
24
+ passCount: 0,
25
+ bindGroupCount: 0,
26
+ });
27
+ });
28
+
29
+ it('reserves the fixed 32-slice IES and Cookie capacities', () => {
30
+ expect(IES_SLICE_CAPACITY).toBe(32);
31
+ expect(COOKIE_SLICE_CAPACITY).toBe(32);
32
+ });
33
+
34
+ it('does not publish a candidate until every resource and upload succeeds', async () => {
35
+ const scope = DeviceScope.create(4, 'renderer');
36
+ const candidate = await createExtendedLightingResourceCandidate({
37
+ device: undefined,
38
+ scope,
39
+ iesSliceCount: 1,
40
+ cookieSliceCount: 1,
41
+ cookieMatrices: 1,
42
+ });
43
+
44
+ expect(candidate.ok).toBe(false);
45
+ expect(inspectExtendedLightingResources(scope)).toMatchObject({
46
+ status: 'empty',
47
+ accepted: false,
48
+ resourceCount: 0,
49
+ });
50
+ });
51
+ });
@@ -0,0 +1,52 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { DeviceScope } from '../device/device-scope';
3
+ import {
4
+ createExtendedLightingResourceCandidate,
5
+ inspectExtendedLightingResources,
6
+ } from '../prepare/extended-lighting/resources';
7
+ import {
8
+ createExtendedLightingState,
9
+ promoteExtendedLightingCandidate,
10
+ } from '../prepare/extended-lighting/state';
11
+
12
+ describe('extended lighting zero-feature integration', () => {
13
+ it('keeps all extension allocations and graph work at exact zero', () => {
14
+ const scope = DeviceScope.create(1, 'renderer');
15
+ const state = createExtendedLightingState(1);
16
+ const inspection = inspectExtendedLightingResources(scope);
17
+
18
+ expect(state.enabled).toBe(false);
19
+ expect(inspection).toEqual({
20
+ topology: 'extendedLighting',
21
+ generation: 1,
22
+ status: 'empty',
23
+ accepted: false,
24
+ resourceCount: 0,
25
+ descriptorBytes: 0,
26
+ uploadCount: 0,
27
+ blendInvalidations: 0,
28
+ passCount: 0,
29
+ });
30
+ expect(promoteExtendedLightingCandidate(state, undefined)).toEqual(state);
31
+ });
32
+
33
+ it('retains accepted resources when a later candidate is rejected', async () => {
34
+ const scope = DeviceScope.create(2, 'renderer');
35
+ const state = createExtendedLightingState(2);
36
+ const rejected = await createExtendedLightingResourceCandidate({
37
+ device: undefined,
38
+ scope,
39
+ iesSliceCount: 33,
40
+ cookieSliceCount: 0,
41
+ cookieMatrices: 0,
42
+ });
43
+
44
+ expect(rejected.ok).toBe(false);
45
+ expect(
46
+ promoteExtendedLightingCandidate(state, rejected.ok ? rejected.value : undefined),
47
+ ).toMatchObject({
48
+ status: 'empty',
49
+ accepted: undefined,
50
+ });
51
+ });
52
+ });
@@ -32,6 +32,7 @@ import { renderLifecycleManifestUrl } from './shader-manifest-fixture';
32
32
 
33
33
  const assemblyDirectory = dirname(fileURLToPath(import.meta.url));
34
34
  const factorySourcePath = resolve(assemblyDirectory, '../assembly/factory.ts');
35
+ const webgpuRendererSourcePath = resolve(assemblyDirectory, '../assembly/webgpu-renderer.ts');
35
36
  const renderTargetHostSourcePath = resolve(assemblyDirectory, '../assembly/render-target-host.ts');
36
37
 
37
38
  function manifestUrl(): string {
@@ -126,6 +127,11 @@ describe('factory contract', () => {
126
127
  expect(source).not.toContain('tone-output');
127
128
  });
128
129
 
130
+ it('forwards the bundler build identity into RenderSystem inspections', () => {
131
+ const source = readFileSync(webgpuRendererSourcePath, 'utf8');
132
+ expect(source).toContain('get build() {\n return internals.bundler?.build;\n },');
133
+ });
134
+
129
135
  it('releases its profiler catalog contribution on dispose', async () => {
130
136
  const profiler = createProfiler();
131
137
  const renderer = await constructRenderer(
@@ -138,6 +144,34 @@ describe('factory contract', () => {
138
144
  expect(profiler.phaseCatalog.render).toEqual([]);
139
145
  });
140
146
 
147
+ it('forwards timing admission to the backend device request', async () => {
148
+ const adapter = new RhiNullAdapter();
149
+ const device = (await adapter.requestDevice()).unwrap();
150
+ let requested: unknown;
151
+ const timingRhi = {
152
+ ...rhi,
153
+ requestAdapter: async () =>
154
+ ok({
155
+ features: new Set(['timestamp-query']),
156
+ limits: adapter.limits,
157
+ requestDevice: async (descriptor?: unknown) => {
158
+ requested = descriptor;
159
+ return ok(device);
160
+ },
161
+ }),
162
+ } as never;
163
+ const renderer = await constructRenderer(
164
+ { getContext: () => null },
165
+ {
166
+ rhi: timingRhi,
167
+ gpuPassTiming: { maxPassesPerFrame: 4, maxFramesInFlight: 1, retentionFrames: 2 },
168
+ },
169
+ { shaderManifestUrl: manifestUrl() },
170
+ );
171
+ expect(requested).toMatchObject({ requiredFeatures: ['timestamp-query'] });
172
+ renderer.dispose();
173
+ });
174
+
141
175
  it('completes the receipt-bound create, attach, draw, observe, recover chain', async () => {
142
176
  const renderer = await constructRenderer(
143
177
  { getContext: () => null },
@@ -1667,6 +1701,15 @@ describe('factory contract', () => {
1667
1701
  expect((await renderer.initialization).ok).toBe(true);
1668
1702
  expect(world.update().ok).toBe(true);
1669
1703
  expect(renderer.draw(input()).ok).toBe(true);
1704
+ expect(renderer.inspect().recovery).toMatchObject({
1705
+ phase: null,
1706
+ fromGeneration: 0,
1707
+ candidateGeneration: 0,
1708
+ attempt: 0,
1709
+ lastOutcome: 'none',
1710
+ rehydratedRoots: 0,
1711
+ staleLossEvents: 0,
1712
+ });
1670
1713
  const beforeLoss = renderer.inspect().bloom;
1671
1714
  const beforeDeviceGeneration = renderer.inspect().temporal.deviceGeneration;
1672
1715
  expect(beforeLoss.state).toBe('active');
@@ -1677,15 +1720,34 @@ describe('factory contract', () => {
1677
1720
  const failed = await renderer.recover();
1678
1721
  expect(failed.ok).toBe(false);
1679
1722
  expect(renderer.health().reason).toBe('device-lost');
1723
+ expect(renderer.inspect().recovery).toMatchObject({
1724
+ phase: null,
1725
+ fromGeneration: 0,
1726
+ candidateGeneration: 1,
1727
+ attempt: 1,
1728
+ lastOutcome: 'failed',
1729
+ rehydratedRoots: 0,
1730
+ staleLossEvents: 0,
1731
+ });
1680
1732
  expect(renderer.inspect().perFramePassNames).toEqual([]);
1681
1733
  expect(renderer.inspect().standardLighting).toBeUndefined();
1682
1734
  const recovered = await renderer.recover();
1683
1735
  expect(recovered.ok).toBe(true);
1684
- // Recovery publishes a device but not a graph. The first post-recovery
1685
- // draw must rebuild both the graph accessors and Standard inspection
1686
- // against the replacement device.
1687
- expect(renderer.inspect().perFramePassNames).toEqual([]);
1688
- expect(renderer.inspect().standardLighting).toBeUndefined();
1736
+ expect(renderer.inspect().recovery).toMatchObject({
1737
+ phase: null,
1738
+ fromGeneration: 0,
1739
+ candidateGeneration: 1,
1740
+ attempt: 2,
1741
+ lastOutcome: 'succeeded',
1742
+ rehydratedRoots: expect.any(Number),
1743
+ staleLossEvents: 0,
1744
+ });
1745
+ expect(renderer.inspect().recovery.rehydratedRoots).toBeGreaterThan(0);
1746
+ // Recovery publishes only after the retained CPU/LKG frame has prepared
1747
+ // the replacement graph and visible residency. The first post-recovery
1748
+ // draw therefore starts with graph accessors and Standard inspection.
1749
+ expect(renderer.inspect().perFramePassNames.length).toBeGreaterThan(0);
1750
+ expect(renderer.inspect().standardLighting).toBeDefined();
1689
1751
  expect(world.update().ok).toBe(true);
1690
1752
  expect(renderer.draw(input()).ok).toBe(true);
1691
1753
  expect(renderer.inspect().perFramePassNames.length).toBeGreaterThan(0);
@@ -1835,7 +1897,11 @@ describe('factory contract', () => {
1835
1897
  await Promise.resolve();
1836
1898
  await Promise.resolve();
1837
1899
  expect(renderer.health().reason).toBe('device-lost');
1838
- expect((await renderer.recover()).ok).toBe(false);
1900
+ const failedRecovery = await renderer.recover();
1901
+ expect(failedRecovery.ok).toBe(false);
1902
+ if (!failedRecovery.ok) {
1903
+ expect(failedRecovery.error.code).toBe('recovery-failed');
1904
+ }
1839
1905
  expect(renderer.health().reason).toBe('device-lost');
1840
1906
  expect(createdReplacementHandles.size).toBeGreaterThan(0);
1841
1907
  expect(
@@ -1874,4 +1940,86 @@ describe('factory contract', () => {
1874
1940
  await renderer.dispose();
1875
1941
  }
1876
1942
  });
1943
+
1944
+ it('reports a structured disposed outcome when recovery is interrupted by dispose', async () => {
1945
+ const adapter = new RhiNullAdapter();
1946
+ const lost = deferred<{ readonly reason: 'unknown'; readonly message: string }>();
1947
+ const recoveryAdapterEntered = deferred<void>();
1948
+ const releaseRecoveryAdapter = deferred<void>();
1949
+ const firstDevice = (await adapter.requestDevice()).unwrap();
1950
+ const lostProxy = new Proxy(firstDevice, {
1951
+ get(target, property) {
1952
+ if (property === 'lost') return lost.promise;
1953
+ const value = Reflect.get(target, property, target);
1954
+ return typeof value === 'function' ? value.bind(target) : value;
1955
+ },
1956
+ });
1957
+ let requestCount = 0;
1958
+ const recoverableRhi = {
1959
+ ...rhi,
1960
+ requestAdapter: async () => {
1961
+ requestCount += 1;
1962
+ if (requestCount === 1) {
1963
+ return ok({
1964
+ features: adapter.features,
1965
+ limits: adapter.limits,
1966
+ requestDevice: async () => ok(lostProxy),
1967
+ } as never);
1968
+ }
1969
+ recoveryAdapterEntered.resolve();
1970
+ await releaseRecoveryAdapter.promise;
1971
+ return ok({
1972
+ features: adapter.features,
1973
+ limits: adapter.limits,
1974
+ requestDevice: async () => ok(firstDevice),
1975
+ } as never);
1976
+ },
1977
+ } as never;
1978
+ const renderer = await constructRenderer(
1979
+ { width: 64, height: 64, getContext: () => null },
1980
+ { rhi: recoverableRhi },
1981
+ { shaderManifestUrl: renderLifecycleManifestUrl() },
1982
+ );
1983
+
1984
+ try {
1985
+ expect((await renderer.initialization).ok).toBe(true);
1986
+ lost.reject({ reason: 'unknown', message: 'forced device loss' });
1987
+ await Promise.resolve();
1988
+ await Promise.resolve();
1989
+ expect(renderer.health().reason).toBe('device-lost');
1990
+
1991
+ const recovery = renderer.recover();
1992
+ await recoveryAdapterEntered.promise;
1993
+ expect(renderer.inspect().recovery.phase).toBe('acquire-adapter');
1994
+ expect((await renderer.dispose()).ok).toBe(true);
1995
+ releaseRecoveryAdapter.resolve();
1996
+
1997
+ const result = await recovery;
1998
+ expect(result.ok).toBe(false);
1999
+ if (!result.ok) {
2000
+ if (result.error.code !== 'recovery-failed') {
2001
+ throw new Error(`Expected recovery-failed, received ${result.error.code}`);
2002
+ }
2003
+ expect(result.error.detail).toMatchObject({
2004
+ phase: 'cleanup',
2005
+ oldGeneration: 0,
2006
+ candidateGeneration: 1,
2007
+ attempt: 1,
2008
+ lastOutcome: 'disposed',
2009
+ rehydratedRoots: 0,
2010
+ staleLossEvents: 0,
2011
+ });
2012
+ }
2013
+ expect(renderer.inspect().recovery).toMatchObject({
2014
+ phase: null,
2015
+ attempt: 1,
2016
+ lastOutcome: 'disposed',
2017
+ rehydratedRoots: 0,
2018
+ staleLossEvents: 0,
2019
+ });
2020
+ } finally {
2021
+ releaseRecoveryAdapter.resolve();
2022
+ await renderer.dispose();
2023
+ }
2024
+ });
1877
2025
  });
@@ -3,7 +3,10 @@ import { describe, expect, it } from 'vitest';
3
3
  import { FALLBACK_BYTES_PER_ROW } from '../ibl/skylight-bind-group';
4
4
 
5
5
  const ownerSource = readFileSync(new URL('../ibl/skylight-bind-group.ts', import.meta.url), 'utf8');
6
- const rendererSource = readFileSync(new URL('../assembly/factory.ts', import.meta.url), 'utf8');
6
+ const rendererSource = readFileSync(
7
+ new URL('../assembly/webgpu-ready.ts', import.meta.url),
8
+ 'utf8',
9
+ );
7
10
 
8
11
  describe('fallback texture row-stride owner', () => {
9
12
  it('keeps both 1x1 fallback upload paths on one owner', () => {
@@ -6,6 +6,7 @@ import {
6
6
  type FrameObservationSource,
7
7
  observeCurrentFrame,
8
8
  } from '../record/frame.js';
9
+ import { validateGraphTargetCaptureReadback } from '../record/frame-snapshot';
9
10
  import type { FrameObservationRequest, FrameReceipt } from '../render-contract';
10
11
 
11
12
  const texture = {} as Texture;
@@ -109,4 +110,18 @@ describe('render current-frame observation producer contract', () => {
109
110
  expect(result.ok).toBe(false);
110
111
  expect(readback).not.toHaveBeenCalled();
111
112
  });
113
+
114
+ it('rejects empty fallback bytes unless the selected rows are neutral', () => {
115
+ const bytes = new Uint8Array(256);
116
+ expect(
117
+ validateGraphTargetCaptureReadback({ bytes, expectedByteLength: bytes.byteLength }),
118
+ ).toEqual({ ok: false, code: 'capture-readback-empty' });
119
+ expect(
120
+ validateGraphTargetCaptureReadback({
121
+ bytes,
122
+ expectedByteLength: bytes.byteLength,
123
+ allowZero: true,
124
+ }),
125
+ ).toEqual({ ok: true });
126
+ });
112
127
  });