@forgeax/engine-render 0.1.21 → 0.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (584) hide show
  1. package/README.md +281 -38
  2. package/dist/assembly/backend-contract.d.ts +13 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/bundler-contract.d.ts +9 -0
  5. package/dist/assembly/bundler-contract.d.ts.map +1 -0
  6. package/dist/assembly/device-feature-admission.d.ts +8 -0
  7. package/dist/assembly/device-feature-admission.d.ts.map +1 -1
  8. package/dist/assembly/extended-lighting-fallback.d.ts +13 -0
  9. package/dist/assembly/extended-lighting-fallback.d.ts.map +1 -0
  10. package/dist/assembly/factory.d.ts +7 -235
  11. package/dist/assembly/factory.d.ts.map +1 -1
  12. package/dist/assembly/host-contract.d.ts +10 -0
  13. package/dist/assembly/host-contract.d.ts.map +1 -1
  14. package/dist/assembly/material/assembly.d.ts +3 -2
  15. package/dist/assembly/material/assembly.d.ts.map +1 -1
  16. package/dist/assembly/material/standard-layer-projection.d.ts +10 -0
  17. package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -0
  18. package/dist/assembly/material-shader-policy.d.ts +168 -0
  19. package/dist/assembly/material-shader-policy.d.ts.map +1 -0
  20. package/dist/assembly/material-shader-prewarm.d.ts +21 -0
  21. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -0
  22. package/dist/assembly/mesh-ssbo-grow.d.ts +88 -0
  23. package/dist/assembly/mesh-ssbo-grow.d.ts.map +1 -0
  24. package/dist/assembly/recovery/device-loss-fanout.d.ts +14 -0
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -0
  26. package/dist/assembly/recovery/generation.d.ts +46 -0
  27. package/dist/assembly/recovery/generation.d.ts.map +1 -0
  28. package/dist/assembly/recovery/recovery-attempt.d.ts +63 -0
  29. package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -0
  30. package/dist/assembly/recovery/renderer-recover.d.ts +115 -0
  31. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -0
  32. package/dist/assembly/renderer-facade.d.ts +10 -0
  33. package/dist/assembly/renderer-facade.d.ts.map +1 -0
  34. package/dist/assembly/renderer-frame-transaction.d.ts +17 -0
  35. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  36. package/dist/assembly/renderer-helpers.d.ts +19 -0
  37. package/dist/assembly/renderer-helpers.d.ts.map +1 -0
  38. package/dist/assembly/renderer-lifecycle.d.ts +34 -0
  39. package/dist/assembly/renderer-lifecycle.d.ts.map +1 -1
  40. package/dist/assembly/shader-prewarm-policy.d.ts +15 -0
  41. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -0
  42. package/dist/assembly/webgpu-ready-contract.d.ts +9 -0
  43. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -0
  44. package/dist/assembly/webgpu-ready.d.ts +55 -0
  45. package/dist/assembly/webgpu-ready.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-renderer.d.ts +152 -0
  47. package/dist/assembly/webgpu-renderer.d.ts.map +1 -0
  48. package/dist/authoring.mjs +1 -1
  49. package/dist/{chunk-PCHBPYML.mjs → chunk-GE3SDD72.mjs} +37 -5
  50. package/dist/chunk-GE3SDD72.mjs.map +1 -0
  51. package/dist/chunk-KZFTK6DO.mjs +1191 -0
  52. package/dist/chunk-KZFTK6DO.mjs.map +1 -0
  53. package/dist/{chunk-FS2KNUQH.mjs → chunk-Q752SHI5.mjs} +332 -568
  54. package/dist/chunk-Q752SHI5.mjs.map +1 -0
  55. package/dist/{chunk-6OPXDQ2E.mjs → chunk-RR5L4SRS.mjs} +33 -294
  56. package/dist/chunk-RR5L4SRS.mjs.map +1 -0
  57. package/dist/chunk-TFH5I7JJ.mjs +296 -0
  58. package/dist/chunk-TFH5I7JJ.mjs.map +1 -0
  59. package/dist/chunk-UQYS7FRM.mjs +1003 -0
  60. package/dist/chunk-UQYS7FRM.mjs.map +1 -0
  61. package/dist/chunk-YKB5DQV7.mjs +345 -0
  62. package/dist/chunk-YKB5DQV7.mjs.map +1 -0
  63. package/dist/{chunk-5YADUCA7.mjs → chunk-YRUYGA4A.mjs} +1189 -1217
  64. package/dist/chunk-YRUYGA4A.mjs.map +1 -0
  65. package/dist/chunk-Z3YYH2MB.mjs +5082 -0
  66. package/dist/chunk-Z3YYH2MB.mjs.map +1 -0
  67. package/dist/cluster-binner.d.ts +5 -0
  68. package/dist/cluster-binner.d.ts.map +1 -1
  69. package/dist/components/index.d.ts +3 -0
  70. package/dist/components/index.d.ts.map +1 -1
  71. package/dist/components/light-helpers.d.ts +4 -0
  72. package/dist/components/light-helpers.d.ts.map +1 -1
  73. package/dist/components/light-probe.d.ts +9 -0
  74. package/dist/components/light-probe.d.ts.map +1 -0
  75. package/dist/components/rect-area-light.d.ts +12 -0
  76. package/dist/components/rect-area-light.d.ts.map +1 -0
  77. package/dist/components/scene-instance.d.ts +4 -0
  78. package/dist/components/scene-instance.d.ts.map +1 -1
  79. package/dist/components/spot-light.d.ts +3 -0
  80. package/dist/components/spot-light.d.ts.map +1 -1
  81. package/dist/construct-renderer.mjs +27276 -23232
  82. package/dist/construct-renderer.mjs.map +1 -1
  83. package/dist/device/device-scope.d.ts +2 -0
  84. package/dist/device/device-scope.d.ts.map +1 -1
  85. package/dist/device/gpu-residency.d.ts +32 -5
  86. package/dist/device/gpu-residency.d.ts.map +1 -1
  87. package/dist/device/lifecycle-transaction.d.ts +2 -0
  88. package/dist/device/lifecycle-transaction.d.ts.map +1 -0
  89. package/dist/environment/frame.d.ts +5 -0
  90. package/dist/environment/frame.d.ts.map +1 -1
  91. package/dist/environment/inspection.d.ts +7 -0
  92. package/dist/environment/inspection.d.ts.map +1 -1
  93. package/dist/environment/lifecycle.d.ts +20 -2
  94. package/dist/environment/lifecycle.d.ts.map +1 -1
  95. package/dist/errors/gpu-driven.d.ts +26 -0
  96. package/dist/errors/gpu-driven.d.ts.map +1 -0
  97. package/dist/errors/index.d.ts +1 -0
  98. package/dist/errors/index.d.ts.map +1 -1
  99. package/dist/errors/recover.d.ts +67 -3
  100. package/dist/errors/recover.d.ts.map +1 -1
  101. package/dist/errors/render.d.ts +39 -1
  102. package/dist/errors/render.d.ts.map +1 -1
  103. package/dist/extract/contracts.d.ts +899 -0
  104. package/dist/extract/contracts.d.ts.map +1 -0
  105. package/dist/extract/gpu-driven.d.ts +50 -0
  106. package/dist/extract/gpu-driven.d.ts.map +1 -0
  107. package/dist/extract/visibility.d.ts.map +1 -1
  108. package/dist/features/host.d.ts +2 -0
  109. package/dist/features/host.d.ts.map +1 -1
  110. package/dist/features/prepared-gpu-work.d.ts +3 -0
  111. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  112. package/dist/features/prepared-graphics-store.d.ts +2 -0
  113. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  114. package/dist/gpu-driven/batch-topology.d.ts +34 -0
  115. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  116. package/dist/gpu-driven/prepared-draw.d.ts +63 -0
  117. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
  118. package/dist/gpu-driven/production-raster.d.ts +126 -2
  119. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  120. package/dist/gpu-driven/view-gpu.d.ts +64 -1
  121. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  122. package/dist/gpu-scene-schema.d.ts +14 -0
  123. package/dist/gpu-scene-schema.d.ts.map +1 -1
  124. package/dist/gpu-scene.d.ts +9 -1
  125. package/dist/gpu-scene.d.ts.map +1 -1
  126. package/dist/gpu-usage.d.ts +0 -1
  127. package/dist/gpu-usage.d.ts.map +1 -1
  128. package/dist/hdrp-buffers.d.ts +3 -3
  129. package/dist/hdrp-buffers.d.ts.map +1 -1
  130. package/dist/ibl/IblPipelineCache.d.ts +7 -6
  131. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  132. package/dist/ibl/skylight-bind-group.d.ts +7 -1
  133. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  134. package/dist/index.d.ts +13 -2
  135. package/dist/index.d.ts.map +1 -1
  136. package/dist/index.mjs +90 -5
  137. package/dist/index.mjs.map +1 -1
  138. package/dist/inspection-types.d.ts +163 -1
  139. package/dist/inspection-types.d.ts.map +1 -1
  140. package/dist/internal.d.ts +9 -0
  141. package/dist/internal.d.ts.map +1 -1
  142. package/dist/internal.mjs +23 -2
  143. package/dist/internal.mjs.map +1 -1
  144. package/dist/light-buffer-layout.d.ts +60 -148
  145. package/dist/light-buffer-layout.d.ts.map +1 -1
  146. package/dist/materials.d.ts +34 -10
  147. package/dist/materials.d.ts.map +1 -1
  148. package/dist/mesh-material-bindings.d.ts +56 -0
  149. package/dist/mesh-material-bindings.d.ts.map +1 -1
  150. package/dist/occlusion-proxy.d.ts +4 -0
  151. package/dist/occlusion-proxy.d.ts.map +1 -0
  152. package/dist/pbr-pipeline.d.ts +58 -21
  153. package/dist/pbr-pipeline.d.ts.map +1 -1
  154. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  155. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -1
  156. package/dist/pipeline/standard-lighting/light-frame.d.ts +3 -3
  157. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -1
  158. package/dist/pipeline/standard-lighting/topology.d.ts +1 -1
  159. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -1
  160. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -1
  161. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  162. package/dist/pipeline-builder.d.ts +2 -0
  163. package/dist/pipeline-builder.d.ts.map +1 -1
  164. package/dist/pipeline-spec.d.ts +1 -1
  165. package/dist/pipeline-spec.d.ts.map +1 -1
  166. package/dist/plugin.d.ts.map +1 -1
  167. package/dist/points-lines/prepare.d.ts +3 -0
  168. package/dist/points-lines/prepare.d.ts.map +1 -1
  169. package/dist/points-lines/standard-owner.d.ts +33 -0
  170. package/dist/points-lines/standard-owner.d.ts.map +1 -0
  171. package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
  172. package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
  173. package/dist/prepare/extended-lighting/resources.d.ts +72 -0
  174. package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
  175. package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
  176. package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
  177. package/dist/prepare/extended-lighting/state.d.ts +24 -0
  178. package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
  179. package/dist/record/frame-lighting.d.ts +8 -6
  180. package/dist/record/frame-lighting.d.ts.map +1 -1
  181. package/dist/record/frame-snapshot.d.ts +55 -10
  182. package/dist/record/frame-snapshot.d.ts.map +1 -1
  183. package/dist/record/frame-targets.d.ts.map +1 -1
  184. package/dist/record/frame.d.ts +21 -5
  185. package/dist/record/frame.d.ts.map +1 -1
  186. package/dist/record/gpu-timing.d.ts +19 -7
  187. package/dist/record/gpu-timing.d.ts.map +1 -1
  188. package/dist/record/helpers.d.ts +0 -20
  189. package/dist/record/helpers.d.ts.map +1 -1
  190. package/dist/record/main-pass-geometry.d.ts +20 -2
  191. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  192. package/dist/record/main-pass-material.d.ts +10 -18
  193. package/dist/record/main-pass-material.d.ts.map +1 -1
  194. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  195. package/dist/record/main-pass.d.ts.map +1 -1
  196. package/dist/record/mesh-ssbo.d.ts +11 -3
  197. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  198. package/dist/record/recovery-pipeline.d.ts +30 -0
  199. package/dist/record/recovery-pipeline.d.ts.map +1 -0
  200. package/dist/record/render-context.d.ts +82 -9
  201. package/dist/record/render-context.d.ts.map +1 -1
  202. package/dist/record/shadow-pass.d.ts.map +1 -1
  203. package/dist/record/typed-frame-graph.d.ts +49 -2
  204. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  205. package/dist/record/view-ubo.d.ts +1 -2
  206. package/dist/record/view-ubo.d.ts.map +1 -1
  207. package/dist/recovery/render-system-candidate.d.ts +65 -0
  208. package/dist/recovery/render-system-candidate.d.ts.map +1 -0
  209. package/dist/reflection/inspection.d.ts +10 -0
  210. package/dist/reflection/inspection.d.ts.map +1 -0
  211. package/dist/reflection/projection.d.ts +49 -0
  212. package/dist/reflection/projection.d.ts.map +1 -1
  213. package/dist/reflection/record-owner.d.ts +60 -0
  214. package/dist/reflection/record-owner.d.ts.map +1 -0
  215. package/dist/render-contract.d.ts +78 -15
  216. package/dist/render-contract.d.ts.map +1 -1
  217. package/dist/render-pipeline.d.ts +7 -0
  218. package/dist/render-pipeline.d.ts.map +1 -1
  219. package/dist/render-system-extract-tail.d.ts +12 -0
  220. package/dist/render-system-extract-tail.d.ts.map +1 -0
  221. package/dist/render-system-extract.d.ts +252 -30
  222. package/dist/render-system-extract.d.ts.map +1 -1
  223. package/dist/render-system.d.ts +140 -5
  224. package/dist/render-system.d.ts.map +1 -1
  225. package/dist/scene/probe-blend-record.d.ts +22 -0
  226. package/dist/scene/probe-blend-record.d.ts.map +1 -0
  227. package/dist/scene/probe-blend.d.ts +142 -0
  228. package/dist/scene/probe-blend.d.ts.map +1 -0
  229. package/dist/scene/render-scene-types.d.ts +0 -6
  230. package/dist/scene/render-scene-types.d.ts.map +1 -1
  231. package/dist/scene/render-scene.d.ts +122 -9
  232. package/dist/scene/render-scene.d.ts.map +1 -1
  233. package/dist/scene/visibility/bounds.d.ts +20 -0
  234. package/dist/scene/visibility/bounds.d.ts.map +1 -0
  235. package/dist/scene/visibility/budget.d.ts +16 -0
  236. package/dist/scene/visibility/budget.d.ts.map +1 -0
  237. package/dist/scene/visibility/facet.d.ts +73 -0
  238. package/dist/scene/visibility/facet.d.ts.map +1 -0
  239. package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
  240. package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
  241. package/dist/scene/visibility/gpu-lod.d.ts +46 -0
  242. package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
  243. package/dist/scene/visibility/inspection.d.ts +132 -0
  244. package/dist/scene/visibility/inspection.d.ts.map +1 -0
  245. package/dist/scene/visibility/lod-selector.d.ts +25 -0
  246. package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
  247. package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
  248. package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
  249. package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
  250. package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
  251. package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
  252. package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
  253. package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
  254. package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
  255. package/dist/scene/visibility/types.d.ts +34 -0
  256. package/dist/scene/visibility/types.d.ts.map +1 -0
  257. package/dist/ssr/admission.d.ts +122 -0
  258. package/dist/ssr/admission.d.ts.map +1 -0
  259. package/dist/ssr/composition.d.ts +32 -0
  260. package/dist/ssr/composition.d.ts.map +1 -0
  261. package/dist/ssr/errors.d.ts +39 -0
  262. package/dist/ssr/errors.d.ts.map +1 -0
  263. package/dist/ssr/identity.d.ts +13 -0
  264. package/dist/ssr/identity.d.ts.map +1 -0
  265. package/dist/systems/skin-palette-allocator.d.ts +1 -1
  266. package/dist/temporal/frame-coordinator.d.ts +13 -0
  267. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  268. package/dist/temporal/frame.d.ts +2 -0
  269. package/dist/temporal/frame.d.ts.map +1 -1
  270. package/dist/temporal/index.mjs +6 -5
  271. package/dist/temporal/taa-history-store.d.ts +15 -1
  272. package/dist/temporal/taa-history-store.d.ts.map +1 -1
  273. package/dist/temporal/transaction.d.ts +5 -0
  274. package/dist/temporal/transaction.d.ts.map +1 -1
  275. package/dist/temporal/view.d.ts +7 -0
  276. package/dist/temporal/view.d.ts.map +1 -1
  277. package/dist/tilemap-chunk-extract-system.d.ts +1 -1
  278. package/dist/typed-render-graph-primitives.d.ts +4 -0
  279. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  280. package/dist/volume/passes.d.ts +8 -4
  281. package/dist/volume/passes.d.ts.map +1 -1
  282. package/package.json +20 -20
  283. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +5 -0
  284. package/src/__tests__/detached-inspection.integration.test.ts +6 -0
  285. package/src/__tests__/device-feature-admission.unit.test.ts +19 -1
  286. package/src/__tests__/device-loss-fanout.unit.test.ts +107 -0
  287. package/src/__tests__/device-scope-lifecycle.unit.test.ts +21 -0
  288. package/src/__tests__/direct-light-snapshot.unit.test.ts +59 -3
  289. package/src/__tests__/environment-generation.integration.test.ts +39 -0
  290. package/src/__tests__/evidence-identity.ts +13 -0
  291. package/src/__tests__/evidence-identity.unit.test.ts +24 -0
  292. package/src/__tests__/expose-renderer-errors.unit.test.ts +34 -0
  293. package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
  294. package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
  295. package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
  296. package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
  297. package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
  298. package/src/__tests__/factory-contract.integration.test.ts +154 -6
  299. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +4 -1
  300. package/src/__tests__/frame-observation.contract.test.ts +15 -0
  301. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
  302. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +1 -0
  303. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +1 -0
  304. package/src/__tests__/gpu-driven-production.integration.test.ts +572 -9
  305. package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
  306. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
  307. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +89 -2
  308. package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
  309. package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
  310. package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
  311. package/src/__tests__/gpu-lod-evidence.ts +188 -0
  312. package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
  313. package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
  314. package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
  315. package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
  316. package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
  317. package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
  318. package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
  319. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
  320. package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
  321. package/src/__tests__/gpu-scene.unit.test.ts +49 -3
  322. package/src/__tests__/ibl/face-uniforms.unit.test.ts +2 -0
  323. package/src/__tests__/ibl-residency-publication.unit.test.ts +113 -0
  324. package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
  325. package/src/__tests__/light-inspection.unit.test.ts +55 -0
  326. package/src/__tests__/light-resource-error.unit.test.ts +43 -0
  327. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
  328. package/src/__tests__/lod-bounds.unit.test.ts +42 -0
  329. package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
  330. package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
  331. package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
  332. package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
  333. package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
  334. package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
  335. package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
  336. package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
  337. package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
  338. package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
  339. package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
  340. package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
  341. package/src/__tests__/lod-selector.profile.test.ts +35 -0
  342. package/src/__tests__/lod-selector.unit.test.ts +68 -0
  343. package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
  344. package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
  345. package/src/__tests__/ltc-resources.unit.test.ts +32 -0
  346. package/src/__tests__/material-contract-inventory.unit.test.ts +41 -9
  347. package/src/__tests__/material-cooked-projection.unit.test.ts +19 -1
  348. package/src/__tests__/material-static-dynamic-route.unit.test.ts +29 -0
  349. package/src/__tests__/material-stride-surface.unit.test.ts +7 -3
  350. package/src/__tests__/materials-standard-contract.unit.test.ts +104 -0
  351. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
  352. package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
  353. package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
  354. package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
  355. package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
  356. package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
  357. package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
  358. package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
  359. package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
  360. package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
  361. package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
  362. package/src/__tests__/occlusion-query.evidence.ts +178 -0
  363. package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
  364. package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
  365. package/src/__tests__/physical-clearcoat.integration.test.ts +89 -0
  366. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
  367. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +1 -1
  368. package/src/__tests__/probe-bindings.unit.test.ts +200 -0
  369. package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
  370. package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
  371. package/src/__tests__/probe-capacity.integration.test.ts +97 -0
  372. package/src/__tests__/probe-recovery.integration.test.ts +104 -0
  373. package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
  374. package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
  375. package/src/__tests__/profiler-phase-token.test.ts +1 -0
  376. package/src/__tests__/recover-error-policy-owner.unit.test.ts +6 -3
  377. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +140 -0
  378. package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
  379. package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
  380. package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
  381. package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
  382. package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
  383. package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
  384. package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
  385. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
  386. package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
  387. package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
  388. package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
  389. package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
  390. package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
  391. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +160 -17
  392. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +47 -0
  393. package/src/__tests__/renderer-generation-assembly.unit.test.ts +77 -0
  394. package/src/__tests__/renderer-generation-failure.unit.test.ts +108 -0
  395. package/src/__tests__/renderer-producer-root-matrix.integration.test.ts +33 -0
  396. package/src/__tests__/renderer-recovery-capability-matrix.unit.test.ts +59 -0
  397. package/src/__tests__/renderer-recovery-contract.unit.test.ts +73 -0
  398. package/src/__tests__/renderer-recovery-lifecycle.unit.test.ts +216 -0
  399. package/src/__tests__/renderer-target-history-recovery.integration.test.ts +80 -0
  400. package/src/__tests__/shader-manifest-fixture.ts +13 -16
  401. package/src/__tests__/shader-stage-surface.unit.test.ts +1 -1
  402. package/src/__tests__/skin-motion-regression.unit.test.ts +22 -0
  403. package/src/__tests__/skinned-shadow-caster.test.ts +2 -2
  404. package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
  405. package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
  406. package/src/__tests__/ssr-composition.unit.test.ts +46 -0
  407. package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
  408. package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
  409. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +67 -0
  410. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +7 -0
  411. package/src/__tests__/standard-layer-projection.unit.test.ts +23 -0
  412. package/src/__tests__/standard-lighting-inspection.integration.test.ts +1 -1
  413. package/src/__tests__/standard-lighting-write.unit.test.ts +66 -2
  414. package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
  415. package/src/__tests__/temporal-view.unit.test.ts +3 -3
  416. package/src/__tests__/transmission-prewarm.unit.test.ts +111 -32
  417. package/src/__tests__/visibility-budget.integration.test.ts +140 -0
  418. package/src/__tests__/visibility-budget.unit.test.ts +70 -0
  419. package/src/__tests__/visibility-extract.integration.test.ts +11 -6
  420. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
  421. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
  422. package/src/__tests__/volumetric-fog-topology.unit.test.ts +3 -1
  423. package/src/assembly/backend-contract.ts +13 -0
  424. package/src/assembly/bundler-contract.ts +9 -0
  425. package/src/assembly/device-feature-admission.ts +26 -9
  426. package/src/assembly/extended-lighting-fallback.ts +216 -0
  427. package/src/assembly/factory.ts +81 -9634
  428. package/src/assembly/host-contract.ts +10 -0
  429. package/src/assembly/material/assembly.ts +18 -2
  430. package/src/assembly/material/standard-layer-projection.ts +16 -0
  431. package/src/assembly/material-shader-policy.ts +854 -0
  432. package/src/assembly/material-shader-prewarm.ts +88 -0
  433. package/src/assembly/mesh-ssbo-grow.ts +270 -0
  434. package/src/assembly/recovery/device-loss-fanout.ts +89 -0
  435. package/src/assembly/recovery/generation.ts +141 -0
  436. package/src/assembly/recovery/recovery-attempt.ts +800 -0
  437. package/src/assembly/recovery/renderer-recover.ts +906 -0
  438. package/src/assembly/renderer-facade.ts +342 -0
  439. package/src/assembly/renderer-frame-transaction.ts +45 -0
  440. package/src/assembly/renderer-helpers.ts +99 -0
  441. package/src/assembly/renderer-lifecycle.ts +159 -0
  442. package/src/assembly/shader-prewarm-policy.ts +157 -0
  443. package/src/assembly/webgpu-ready-contract.ts +14 -0
  444. package/src/assembly/webgpu-ready.ts +4079 -0
  445. package/src/assembly/webgpu-renderer.ts +4095 -0
  446. package/src/cluster-binner.ts +31 -0
  447. package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
  448. package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
  449. package/src/components/camera.ts +1 -1
  450. package/src/components/index.ts +3 -0
  451. package/src/components/light-helpers.ts +52 -1
  452. package/src/components/light-probe.ts +13 -0
  453. package/src/components/rect-area-light.ts +15 -0
  454. package/src/components/scene-instance.ts +6 -0
  455. package/src/components/spot-light.ts +3 -0
  456. package/src/debug-draw-glue.ts +1 -1
  457. package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
  458. package/src/device/device-scope.ts +35 -6
  459. package/src/device/gpu-residency.ts +334 -35
  460. package/src/device/lifecycle-transaction.ts +12 -0
  461. package/src/environment/frame.ts +6 -0
  462. package/src/environment/inspection.ts +10 -0
  463. package/src/environment/lifecycle.ts +122 -9
  464. package/src/errors/gpu-driven.ts +92 -0
  465. package/src/errors/index.ts +1 -0
  466. package/src/errors/recover.ts +108 -5
  467. package/src/errors/render.ts +72 -1
  468. package/src/extract/camera.ts +3 -3
  469. package/src/extract/contracts.ts +974 -0
  470. package/src/extract/gpu-driven.ts +108 -0
  471. package/src/extract/visibility.ts +0 -23
  472. package/src/features/host.ts +16 -0
  473. package/src/features/prepared-gpu-work.ts +20 -2
  474. package/src/features/prepared-graphics-store.ts +17 -0
  475. package/src/gpu-driven/batch-topology.ts +206 -28
  476. package/src/gpu-driven/prepared-draw.ts +208 -0
  477. package/src/gpu-driven/production-raster.ts +1046 -39
  478. package/src/gpu-driven/view-gpu.ts +411 -29
  479. package/src/gpu-scene-schema.ts +13 -0
  480. package/src/gpu-scene.ts +137 -67
  481. package/src/gpu-usage.ts +0 -1
  482. package/src/hdrp-buffers.ts +6 -6
  483. package/src/ibl/IblPipelineCache.ts +134 -50
  484. package/src/ibl/skylight-bind-group.ts +26 -0
  485. package/src/index.ts +83 -1
  486. package/src/inspection-types.ts +220 -1
  487. package/src/internal.ts +38 -0
  488. package/src/light-buffer-layout.ts +157 -324
  489. package/src/materials.ts +278 -47
  490. package/src/mesh-material-bindings.ts +59 -0
  491. package/src/occlusion-proxy.ts +64 -0
  492. package/src/pbr-pipeline.ts +290 -60
  493. package/src/pipeline/standard-forward-lane.ts +47 -0
  494. package/src/pipeline/standard-lighting/graph.ts +2 -1
  495. package/src/pipeline/standard-lighting/light-frame.ts +3 -2
  496. package/src/pipeline/standard-lighting/topology.ts +1 -1
  497. package/src/pipeline/standard-lighting/transport.ts +2 -1
  498. package/src/pipeline/standard-pipeline.ts +2 -0
  499. package/src/pipeline-builder.ts +5 -2
  500. package/src/pipeline-spec.ts +12 -1
  501. package/src/plugin.ts +4 -0
  502. package/src/points-lines/__tests__/cache-recovery.unit.test.ts +22 -0
  503. package/src/points-lines/prepare.ts +9 -0
  504. package/src/points-lines/standard-owner.ts +403 -0
  505. package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
  506. package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
  507. package/src/prepare/extended-lighting/resources.ts +389 -0
  508. package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
  509. package/src/prepare/extended-lighting/state.ts +92 -0
  510. package/src/record/__tests__/frame-targets-recovery.unit.test.ts +60 -0
  511. package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
  512. package/src/record/__tests__/main-pass-geometry.unit.test.ts +26 -1
  513. package/src/record/__tests__/mesh-ssbo.unit.test.ts +38 -0
  514. package/src/record/__tests__/recovery-pipeline.unit.test.ts +124 -0
  515. package/src/record/__tests__/sprite-material-abi.unit.test.ts +28 -13
  516. package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +47 -4
  517. package/src/record/__tests__/temporal-payload.unit.test.ts +29 -28
  518. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +21 -2
  519. package/src/record/frame-lighting.ts +252 -53
  520. package/src/record/frame-snapshot.ts +72 -12
  521. package/src/record/frame-targets.ts +11 -1
  522. package/src/record/frame.ts +416 -95
  523. package/src/record/gpu-timing.ts +108 -44
  524. package/src/record/helpers.ts +1 -59
  525. package/src/record/main-pass-geometry.ts +434 -44
  526. package/src/record/main-pass-material.ts +324 -210
  527. package/src/record/main-pass-sprite-draws.ts +58 -92
  528. package/src/record/main-pass.ts +94 -6
  529. package/src/record/mesh-ssbo.ts +79 -46
  530. package/src/record/recovery-pipeline.ts +695 -0
  531. package/src/record/render-context.ts +99 -7
  532. package/src/record/shadow-pass.ts +66 -40
  533. package/src/record/typed-frame-graph.ts +270 -84
  534. package/src/record/view-ubo.ts +17 -27
  535. package/src/recovery/render-system-candidate.ts +839 -0
  536. package/src/reflection/inspection.ts +67 -0
  537. package/src/reflection/projection.ts +196 -1
  538. package/src/reflection/record-owner.ts +1283 -0
  539. package/src/render-contract.ts +82 -12
  540. package/src/render-pipeline.ts +5 -0
  541. package/src/render-system-extract-tail.ts +2983 -0
  542. package/src/render-system-extract.ts +290 -2784
  543. package/src/render-system.ts +1597 -1192
  544. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
  545. package/src/scene/probe-blend-record.ts +54 -0
  546. package/src/scene/probe-blend.ts +813 -0
  547. package/src/scene/render-scene-types.ts +0 -7
  548. package/src/scene/render-scene.ts +972 -184
  549. package/src/scene/visibility/bounds.ts +57 -0
  550. package/src/scene/visibility/budget.ts +40 -0
  551. package/src/scene/visibility/facet.ts +400 -0
  552. package/src/scene/visibility/gpu-frame-timing.ts +101 -0
  553. package/src/scene/visibility/gpu-lod.ts +119 -0
  554. package/src/scene/visibility/inspection.ts +313 -0
  555. package/src/scene/visibility/lod-selector.ts +84 -0
  556. package/src/scene/visibility/occlusion-confidence.ts +478 -0
  557. package/src/scene/visibility/occlusion-pass.ts +165 -0
  558. package/src/scene/visibility/occlusion-query-pool.ts +178 -0
  559. package/src/scene/visibility/occlusion-runtime.ts +672 -0
  560. package/src/scene/visibility/types.ts +50 -0
  561. package/src/ssr/admission.ts +451 -0
  562. package/src/ssr/composition.ts +73 -0
  563. package/src/ssr/errors.ts +76 -0
  564. package/src/ssr/identity.ts +12 -0
  565. package/src/systems/skin-palette-allocator.ts +1 -1
  566. package/src/temporal/frame-coordinator.ts +30 -1
  567. package/src/temporal/frame.ts +14 -1
  568. package/src/temporal/taa-history-store.ts +46 -2
  569. package/src/temporal/temporal-view.ts +1 -1
  570. package/src/temporal/transaction.ts +9 -0
  571. package/src/temporal/view.ts +11 -0
  572. package/src/tilemap-chunk-extract-system.ts +5 -5
  573. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +19 -12
  574. package/src/typed-render-graph-primitives.ts +48 -0
  575. package/src/volume/passes.ts +46 -49
  576. package/dist/.tsbuildinfo +0 -1
  577. package/dist/chunk-5YADUCA7.mjs.map +0 -1
  578. package/dist/chunk-6OPXDQ2E.mjs.map +0 -1
  579. package/dist/chunk-BXBQQKFQ.mjs +0 -67
  580. package/dist/chunk-BXBQQKFQ.mjs.map +0 -1
  581. package/dist/chunk-FS2KNUQH.mjs.map +0 -1
  582. package/dist/chunk-PCHBPYML.mjs.map +0 -1
  583. package/dist/chunk-VFPLTKCU.mjs +0 -192
  584. package/dist/chunk-VFPLTKCU.mjs.map +0 -1
@@ -0,0 +1,1003 @@
1
+ import { CUBE_CAMERA_FACE_ORDER, createVisibilityBudget, PointShapeValue, pointShapeFromU32 } from './chunk-Q752SHI5.mjs';
2
+ import { PointsLinesBudgetExceededError, PointsLinesStyleUnsupportedError, PointsLinesMaterialUnsupportedError, PointsLinesInvalidStyleError, PointsLinesTopologyMismatchError } from './chunk-RR5L4SRS.mjs';
3
+ import { err, ok } from '@forgeax/engine-types';
4
+ import { mat4 } from '@forgeax/engine-math';
5
+ import { validateR32FloatReceipt } from '@forgeax/engine-rhi';
6
+
7
+ function invalidStyle(input, component, field, value, expected) {
8
+ return err(new PointsLinesInvalidStyleError({ entity: input.entity, component, field, value, expected }));
9
+ }
10
+ function topologyMismatch(input, submesh, expected, actual) {
11
+ return err(new PointsLinesTopologyMismatchError({ entity: input.entity, submesh, expected, actual }));
12
+ }
13
+ function checkStyle(input) {
14
+ const hasPoints = input.points !== void 0;
15
+ const hasLines = input.lines !== void 0;
16
+ if (hasPoints && hasLines) {
17
+ return invalidStyle(
18
+ input,
19
+ "Points/Lines",
20
+ "components",
21
+ "Points + Lines",
22
+ "exactly one style component"
23
+ );
24
+ }
25
+ if (!hasPoints && !hasLines) {
26
+ return invalidStyle(input, "Points/Lines", "components", void 0, "one style component");
27
+ }
28
+ if (hasPoints) {
29
+ const sizePx = input.points?.sizePx ?? 4;
30
+ const shapeValue = input.points?.shape ?? PointShapeValue.square;
31
+ const shape = pointShapeFromU32(shapeValue);
32
+ if (!Number.isFinite(sizePx) || sizePx <= 0) {
33
+ return invalidStyle(input, "Points", "sizePx", sizePx, "finite sizePx > 0");
34
+ }
35
+ if (shape === void 0) {
36
+ return invalidStyle(input, "Points", "shape", shapeValue, "shape is 'square' or 'circle'");
37
+ }
38
+ return ok({ component: "Points", shape, sizePx });
39
+ }
40
+ const widthPx = input.lines?.widthPx ?? 1;
41
+ if (!Number.isFinite(widthPx) || widthPx <= 0) {
42
+ return invalidStyle(input, "Lines", "widthPx", widthPx, "finite widthPx > 0");
43
+ }
44
+ return ok({ component: "Lines", widthPx });
45
+ }
46
+ function checkTopology(input, component) {
47
+ const expected = component === "Points" ? "point-list" : "line-list";
48
+ let pointCount = 0;
49
+ let segmentCount = 0;
50
+ const acceptedSubmeshes = [];
51
+ let sawNonEmpty = false;
52
+ for (const [submeshIndex, submesh] of input.mesh.submeshes.entries()) {
53
+ const indexed = input.mesh.indices !== void 0 && submesh.indexCount > 0;
54
+ const elementCount = indexed ? submesh.indexCount : submesh.vertexCount;
55
+ if (elementCount === 0) continue;
56
+ sawNonEmpty = true;
57
+ if (component === "Lines" && submesh.topology === "line-strip") {
58
+ return err(
59
+ new PointsLinesStyleUnsupportedError({
60
+ lane: "admission",
61
+ field: "topology",
62
+ member: "line-strip",
63
+ supported: ["line-list"]
64
+ })
65
+ );
66
+ }
67
+ if (submesh.topology !== expected) {
68
+ return topologyMismatch(input, submeshIndex, expected, submesh.topology);
69
+ }
70
+ if (component === "Lines" && elementCount % 2 !== 0) {
71
+ return topologyMismatch(input, submeshIndex, "line-list pairs", "line-list odd tail");
72
+ }
73
+ acceptedSubmeshes.push(submeshIndex);
74
+ if (component === "Points") pointCount += elementCount;
75
+ else segmentCount += elementCount / 2;
76
+ }
77
+ if (!sawNonEmpty) return topologyMismatch(input, 0, expected, "empty-range");
78
+ return ok({ pointCount, segmentCount, submeshes: acceptedSubmeshes });
79
+ }
80
+ function checkMaterial(input) {
81
+ const passes = input.material.passes ?? [];
82
+ const unlitModules = /* @__PURE__ */ new Set(["forgeax_material::unlit", "forgeax::default-unlit"]);
83
+ if (passes.length !== 1 || passes[0] === void 0) {
84
+ const pass2 = passes.find(
85
+ (candidate) => candidate.name === "deferred" || candidate.name === "shadow-caster"
86
+ ) ?? passes[0];
87
+ return err(
88
+ new PointsLinesMaterialUnsupportedError({
89
+ entity: input.entity,
90
+ material: input.materialId ?? "<anonymous>",
91
+ pass: pass2?.name ?? "<empty>",
92
+ module: pass2?.program.module ?? "<empty>",
93
+ reason: "points-lines admission requires one unlit forward pass"
94
+ })
95
+ );
96
+ }
97
+ const pass = passes[0];
98
+ const lightMode = pass.renderState?.tags?.LightMode;
99
+ if (!unlitModules.has(pass.program.module) || pass.name !== "forward" || lightMode === "ShadowCaster") {
100
+ return err(
101
+ new PointsLinesMaterialUnsupportedError({
102
+ entity: input.entity,
103
+ material: input.materialId ?? "<anonymous>",
104
+ pass: pass.name,
105
+ module: pass.program.module,
106
+ reason: "points-lines admission requires an engine-owned unlit forward pass"
107
+ })
108
+ );
109
+ }
110
+ return ok(void 0);
111
+ }
112
+ function admitPointsLines(input) {
113
+ const style = checkStyle(input);
114
+ if (!style.ok) return style;
115
+ const topology = checkTopology(input, style.value.component);
116
+ if (!topology.ok) return topology;
117
+ const material = checkMaterial(input);
118
+ if (!material.ok) return material;
119
+ if (style.value.component === "Points" && input.limits?.maxPoints !== void 0) {
120
+ if (topology.value.pointCount > input.limits.maxPoints) {
121
+ return err(
122
+ new PointsLinesBudgetExceededError({
123
+ lane: "admission",
124
+ requested: topology.value.pointCount,
125
+ limit: input.limits.maxPoints,
126
+ unit: "points"
127
+ })
128
+ );
129
+ }
130
+ }
131
+ if (style.value.component === "Lines" && input.limits?.maxSegments !== void 0) {
132
+ if (topology.value.segmentCount > input.limits.maxSegments) {
133
+ return err(
134
+ new PointsLinesBudgetExceededError({
135
+ lane: "admission",
136
+ requested: topology.value.segmentCount,
137
+ limit: input.limits.maxSegments,
138
+ unit: "segments"
139
+ })
140
+ );
141
+ }
142
+ }
143
+ return ok({ ...style.value, ...topology.value });
144
+ }
145
+
146
+ // src/point-shadow-inspection.ts
147
+ function inspectPointShadow(snapshots, shadowAtlasCapacity) {
148
+ const requested = snapshots.length;
149
+ const admitted = snapshots.reduce(
150
+ (count, snapshot) => snapshot.shadowAtlasLayer >= 0 && snapshot.shadowAtlasLayer < shadowAtlasCapacity ? count + 1 : count,
151
+ 0
152
+ );
153
+ const status = requested === 0 ? "inactive" : requested > shadowAtlasCapacity || admitted !== requested ? "over-budget" : "ready";
154
+ return Object.freeze({
155
+ status,
156
+ requested,
157
+ admitted,
158
+ // A point shadow only samples an atlas after it owns an atlas layer. Keep
159
+ // these names explicit for AI diagnostics while deriving both from the
160
+ // one layer projection above.
161
+ shadowed: admitted,
162
+ shadowAtlasOccupancy: admitted,
163
+ shadowAtlasCapacity
164
+ });
165
+ }
166
+
167
+ // src/volume/inspection.ts
168
+ function resourceStage(input) {
169
+ if (!input.authored || input.recovery === void 0) return "none";
170
+ if (input.recovery.status === "candidate") return "candidate";
171
+ if (input.recovery.status === "recovering") return "recovering";
172
+ if (input.recovery.status === "degraded") return "lkg";
173
+ return "accepted";
174
+ }
175
+ function inspectVolumetricFog(input) {
176
+ const recovery = input.recovery;
177
+ const status = !input.authored ? "off" : input.capability === "unavailable" ? "unavailable" : input.degraded === true || recovery?.status === "degraded" ? "degraded" : "available";
178
+ return Object.freeze({
179
+ status,
180
+ resourceStage: resourceStage(input),
181
+ guid: recovery?.guid,
182
+ generation: recovery?.generation,
183
+ digest: input.acceptedDigest,
184
+ candidateGeneration: recovery?.candidateGeneration,
185
+ candidateDigest: recovery?.candidateDigest,
186
+ lkgGeneration: recovery?.lkgGeneration,
187
+ candidateFailure: recovery?.candidateFailure,
188
+ deviceEpoch: recovery?.deviceEpoch ?? 0,
189
+ format: input.format,
190
+ passCount: input.passCount ?? 0,
191
+ sampleCount: input.sampleCount ?? 0,
192
+ memoryBytes: input.memoryBytes ?? 0,
193
+ resourceFacts: input.resourceFacts,
194
+ selectedLight: recovery?.selectedLight,
195
+ candidateSelectedLight: recovery?.candidateSelectedLight
196
+ });
197
+ }
198
+ var FACE_ORIENTATION = [
199
+ { direction: [1, 0, 0], up: [0, 1, 0] },
200
+ { direction: [-1, 0, 0], up: [0, 1, 0] },
201
+ { direction: [0, 1, 0], up: [0, 0, -1] },
202
+ { direction: [0, -1, 0], up: [0, 0, 1] },
203
+ { direction: [0, 0, 1], up: [0, 1, 0] },
204
+ { direction: [0, 0, -1], up: [0, 1, 0] }
205
+ ];
206
+ function assertRange(near, far) {
207
+ if (!Number.isFinite(near) || near <= 0 || !Number.isFinite(far) || far <= near) {
208
+ throw new RangeError("CubeCamera requires finite near > 0 and far > near.");
209
+ }
210
+ }
211
+ function buildCubeCameraFaceViews(input) {
212
+ assertRange(input.near, input.far);
213
+ const views = [];
214
+ for (const [index, face] of CUBE_CAMERA_FACE_ORDER.entries()) {
215
+ const orientation = FACE_ORIENTATION[index];
216
+ if (orientation === void 0)
217
+ throw new Error(`CubeCamera face orientation missing at ${index}`);
218
+ const target = [
219
+ (input.position[0] ?? 0) + orientation.direction[0],
220
+ (input.position[1] ?? 0) + orientation.direction[1],
221
+ (input.position[2] ?? 0) + orientation.direction[2]
222
+ ];
223
+ const view = mat4.lookAt(mat4.create(), input.position, target, orientation.up);
224
+ const projection = mat4.perspective(mat4.create(), Math.PI / 2, 1, input.near, input.far);
225
+ const viewProjection = mat4.multiply(mat4.create(), projection, view);
226
+ views.push({
227
+ position: input.position,
228
+ face,
229
+ direction: orientation.direction,
230
+ up: orientation.up,
231
+ near: input.near,
232
+ far: input.far,
233
+ view,
234
+ projection,
235
+ viewProjection
236
+ });
237
+ }
238
+ return views;
239
+ }
240
+
241
+ // src/reflection/filter.ts
242
+ function createProbeFilterState(input) {
243
+ return {
244
+ probeIndex: input.probeIndex,
245
+ faceCount: input.faceCount ?? 6,
246
+ mipCount: input.mipCount,
247
+ cursor: 0,
248
+ activeGeneration: input.activeGeneration ?? 0
249
+ };
250
+ }
251
+ function advanceProbeFilter(state) {
252
+ const total = state.faceCount * state.mipCount;
253
+ if (state.cursor >= total) return void 0;
254
+ return {
255
+ probeIndex: state.probeIndex,
256
+ faceIndex: state.cursor % state.faceCount,
257
+ mipLevel: Math.floor(state.cursor / state.faceCount)
258
+ };
259
+ }
260
+ function commitProbeFilterStep(state, success) {
261
+ if (!success) return state;
262
+ const nextCursor = state.cursor + 1;
263
+ const complete = nextCursor >= state.faceCount * state.mipCount;
264
+ return {
265
+ ...state,
266
+ cursor: nextCursor,
267
+ activeGeneration: complete ? state.activeGeneration + 1 : state.activeGeneration
268
+ };
269
+ }
270
+ function probeFilterIsSteady(state) {
271
+ return state.cursor >= state.faceCount * state.mipCount;
272
+ }
273
+ function normalize(vector) {
274
+ const length = Math.hypot(vector[0], vector[1], vector[2]);
275
+ if (length === 0) return [0, 0, 1];
276
+ return [vector[0] / length, vector[1] / length, vector[2] / length];
277
+ }
278
+ function boxProjectReflectionDirection(direction, boxCenter, halfExtents, point) {
279
+ const ray = normalize(direction);
280
+ let distance = Number.POSITIVE_INFINITY;
281
+ for (let axis = 0; axis < 3; axis += 1) {
282
+ const component = ray[axis] ?? 0;
283
+ if (component === 0) continue;
284
+ const extent = halfExtents[axis] ?? 0;
285
+ const edge = component > 0 ? (boxCenter[axis] ?? 0) + extent : (boxCenter[axis] ?? 0) - extent;
286
+ const candidate = (edge - (point[axis] ?? 0)) / component;
287
+ if (candidate > 0) distance = Math.min(distance, candidate);
288
+ }
289
+ if (!Number.isFinite(distance)) return ray;
290
+ return normalize([
291
+ (point[0] ?? 0) + ray[0] * distance - (boxCenter[0] ?? 0),
292
+ (point[1] ?? 0) + ray[1] * distance - (boxCenter[1] ?? 0),
293
+ (point[2] ?? 0) + ray[2] * distance - (boxCenter[2] ?? 0)
294
+ ]);
295
+ }
296
+
297
+ // src/reflection/gpu-table.ts
298
+ function buildReflectionProbeTable(rows) {
299
+ const ordered = rows.slice().sort((a, b) => a.index - b.index);
300
+ const indices = /* @__PURE__ */ new Map();
301
+ for (const row of ordered) {
302
+ if (row.primitiveKey !== void 0) indices.set(row.primitiveKey, row.index);
303
+ }
304
+ const indexFor = (primitiveKey2) => indices.get(primitiveKey2);
305
+ return {
306
+ rows: Object.freeze(ordered),
307
+ cpuIndexByPrimitive: indexFor,
308
+ gpuIndexByPrimitive: indexFor
309
+ };
310
+ }
311
+ function reflectionProbeTableBytes(table) {
312
+ return table.rows.length * 48;
313
+ }
314
+
315
+ // src/reflection/inspection.ts
316
+ function recoveryFor(receipt, failure2) {
317
+ if (failure2 !== void 0) {
318
+ const code = failure2.code.toLowerCase();
319
+ if (code.includes("device") || code.includes("format") || code.includes("capability")) {
320
+ return "rebuild";
321
+ }
322
+ if (failure2.stage === "prepare" || failure2.stage === "filter") return "recapture";
323
+ if (failure2.stage === "build" || failure2.stage === "encode") return "rebuild";
324
+ if (failure2.stage === "finish" || failure2.stage === "submit") return "retry";
325
+ if (failure2.stage === "completion") {
326
+ if (receipt.source === "probe" && (receipt.state === "active" || receipt.state === "lkg")) {
327
+ return "use-LKG";
328
+ }
329
+ if (receipt.source === "skylight" && (receipt.state === "active" || receipt.state === "lkg")) {
330
+ return "use-Skylight";
331
+ }
332
+ if (receipt.source === "neutral" && receipt.state === "neutral") return "use-neutral";
333
+ return "retry";
334
+ }
335
+ }
336
+ if (receipt.source === "probe" && (receipt.state === "active" || receipt.state === "lkg")) {
337
+ return "use-LKG";
338
+ }
339
+ if (receipt.source === "skylight" || receipt.state === "lkg") return "use-Skylight";
340
+ return "use-neutral";
341
+ }
342
+ function inspectReflectionFallback(receipt, failure2) {
343
+ return {
344
+ receipt,
345
+ recoveryAction: recoveryFor(receipt, failure2),
346
+ ...failure2 === void 0 ? {} : {
347
+ failureStage: failure2.stage,
348
+ failureCode: failure2.code,
349
+ expected: failure2.expected,
350
+ ...failure2.detail === void 0 ? {} : { detail: failure2.detail }
351
+ }
352
+ };
353
+ }
354
+
355
+ // src/reflection/projection.ts
356
+ var REFLECTION_PROBE_BYTES_PER_TEXEL = 8;
357
+ var DEFAULT_REFLECTION_PROBE_LIMITS = Object.freeze({
358
+ maxProbes: 16,
359
+ maxResolution: 256,
360
+ maxBytes: 64 * 1024 * 1024
361
+ });
362
+ function validateReflectionProbeInput(input) {
363
+ for (let index = 0; index < input.halfExtents.length; index += 1) {
364
+ const value = input.halfExtents[index];
365
+ if (value === void 0 || !Number.isFinite(value) || value <= 0) {
366
+ return {
367
+ ok: false,
368
+ error: {
369
+ code: "reflection-probe-input-invalid",
370
+ field: `halfExtents[${index}]`,
371
+ value,
372
+ expected: "a finite number greater than zero"
373
+ }
374
+ };
375
+ }
376
+ }
377
+ if (!Number.isFinite(input.priority)) {
378
+ return {
379
+ ok: false,
380
+ error: {
381
+ code: "reflection-probe-input-invalid",
382
+ field: "priority",
383
+ value: input.priority,
384
+ expected: "a finite number"
385
+ }
386
+ };
387
+ }
388
+ if (!Number.isFinite(input.intensity) || input.intensity < 0) {
389
+ return {
390
+ ok: false,
391
+ error: {
392
+ code: "reflection-probe-input-invalid",
393
+ field: "intensity",
394
+ value: input.intensity,
395
+ expected: "a finite number greater than or equal to zero"
396
+ }
397
+ };
398
+ }
399
+ if (!Number.isInteger(input.resolution) || input.resolution <= 0) {
400
+ return {
401
+ ok: false,
402
+ error: {
403
+ code: "reflection-probe-input-invalid",
404
+ field: "resolution",
405
+ value: input.resolution,
406
+ expected: "a positive integer"
407
+ }
408
+ };
409
+ }
410
+ return { ok: true };
411
+ }
412
+ function estimateReflectionProbeBytes(resolution, limits = DEFAULT_REFLECTION_PROBE_LIMITS) {
413
+ const maxResolution = limits.maxResolution ?? DEFAULT_REFLECTION_PROBE_LIMITS.maxResolution;
414
+ const clamped = Math.min(resolution, maxResolution);
415
+ let mipTexels = 0;
416
+ for (let size = clamped; size >= 1; size = Math.floor(size / 2)) {
417
+ mipTexels += size * size;
418
+ }
419
+ return mipTexels * 6 * REFLECTION_PROBE_BYTES_PER_TEXEL;
420
+ }
421
+ function admitReflectionProbe(input, current, limits = DEFAULT_REFLECTION_PROBE_LIMITS) {
422
+ const maxProbes = limits.maxProbes ?? DEFAULT_REFLECTION_PROBE_LIMITS.maxProbes;
423
+ const maxBytes = limits.maxBytes ?? DEFAULT_REFLECTION_PROBE_LIMITS.maxBytes;
424
+ const maxResolution = limits.maxResolution ?? DEFAULT_REFLECTION_PROBE_LIMITS.maxResolution;
425
+ const requested = estimateReflectionProbeBytes(input.resolution, { maxResolution });
426
+ if (input.resolution > maxResolution || current.acceptedCount >= maxProbes || current.acceptedBytes + requested > maxBytes) {
427
+ return {
428
+ ok: false,
429
+ error: {
430
+ code: "reflection-probe-budget-exceeded",
431
+ requested,
432
+ activeCount: current.acceptedCount,
433
+ activeBytes: current.acceptedBytes,
434
+ maxProbes,
435
+ maxBytes
436
+ }
437
+ };
438
+ }
439
+ return { ok: true, acceptedBytes: current.acceptedBytes + requested };
440
+ }
441
+ function resolveReflectionFallbackSource(selection, probeReady, skylightAvailable = true) {
442
+ if (selection.kind === "probe" && probeReady) return "probe";
443
+ if (skylightAvailable) return "skylight";
444
+ return "neutral";
445
+ }
446
+ function reflectionFallbackCoverage(source, fact, selection) {
447
+ if (source === "neutral") return 0;
448
+ if (source === "skylight") return 1;
449
+ if (fact === void 0 || selection.kind !== "probe") return 0;
450
+ const normalized = Math.sqrt(Math.max(0, selection.normalizedDistance));
451
+ return Math.max(0, Math.min(1, 1 - normalized / Math.sqrt(3)));
452
+ }
453
+ function reflectionFallbackSourceKey(source, selection, skylight) {
454
+ if (source === "probe" && selection.kind === "probe") {
455
+ return `probe:${selection.worldId}:${selection.entityKey}`;
456
+ }
457
+ if (source === "skylight" && skylight !== void 0) {
458
+ return `skylight:${skylight.entityHandle}:${skylight.equirectHandle}`;
459
+ }
460
+ return source;
461
+ }
462
+ function reflectionFallbackProjectionSignature(input) {
463
+ return JSON.stringify({
464
+ renderableKey: input.renderableKey,
465
+ sourceKey: input.sourceKey,
466
+ source: input.source,
467
+ coverage: input.coverage,
468
+ extent: input.extent,
469
+ brdfSignature: input.brdfSignature
470
+ });
471
+ }
472
+ function deriveReflectionFallbackProjection(input) {
473
+ if (!Number.isFinite(input.coverage) || input.coverage < 0 || input.coverage > 1) {
474
+ return {
475
+ ok: false,
476
+ error: {
477
+ code: "reflection-fallback-input-invalid",
478
+ field: "coverage",
479
+ expected: "a finite number between zero and one"
480
+ }
481
+ };
482
+ }
483
+ if (input.extent?.some((value) => !Number.isFinite(value) || value <= 0)) {
484
+ return {
485
+ ok: false,
486
+ error: {
487
+ code: "reflection-fallback-input-invalid",
488
+ field: "extent",
489
+ expected: "three finite numbers greater than zero"
490
+ }
491
+ };
492
+ }
493
+ if (input.linearHdr.some((value) => !Number.isFinite(value))) {
494
+ return {
495
+ ok: false,
496
+ error: {
497
+ code: "reflection-fallback-input-invalid",
498
+ field: "linearHdr",
499
+ expected: "four finite linear HDR values"
500
+ }
501
+ };
502
+ }
503
+ if (input.brdfSignature.length === 0) {
504
+ return {
505
+ ok: false,
506
+ error: {
507
+ code: "reflection-fallback-input-invalid",
508
+ field: "brdfSignature",
509
+ expected: "a non-empty BRDF signature"
510
+ }
511
+ };
512
+ }
513
+ const linearHdr = input.source === "neutral" ? [0, 0, 0, 0] : [...input.linearHdr];
514
+ return {
515
+ ok: true,
516
+ value: Object.freeze({
517
+ ...input.renderableKey === void 0 ? {} : { renderableKey: input.renderableKey },
518
+ ...input.sourceKey === void 0 ? {} : { sourceKey: input.sourceKey },
519
+ source: input.source,
520
+ coverage: input.coverage,
521
+ ...input.extent === void 0 ? {} : {
522
+ extent: Object.freeze([...input.extent])
523
+ },
524
+ linearHdr: Object.freeze(linearHdr),
525
+ brdfSignature: input.brdfSignature
526
+ })
527
+ };
528
+ }
529
+ function contains(fact, point) {
530
+ return fact.halfExtents.every((extent, axis) => {
531
+ const center = fact.center[axis] ?? 0;
532
+ const coordinate = point[axis] ?? 0;
533
+ return Math.abs(coordinate - center) <= extent;
534
+ });
535
+ }
536
+ function normalizedDistance(fact, point) {
537
+ let squared = 0;
538
+ for (let axis = 0; axis < 3; axis += 1) {
539
+ const delta = (point[axis] ?? 0) - (fact.center[axis] ?? 0);
540
+ const extent = fact.halfExtents[axis] ?? 1;
541
+ squared += (delta / extent) ** 2;
542
+ }
543
+ return squared;
544
+ }
545
+ function isBetter(candidate, current, facts) {
546
+ const candidateFact = facts.find(
547
+ (fact) => fact.worldId === candidate.worldId && fact.entityKey === candidate.entityKey
548
+ );
549
+ const currentFact = facts.find(
550
+ (fact) => fact.worldId === current.worldId && fact.entityKey === current.entityKey
551
+ );
552
+ if (candidateFact === void 0 || currentFact === void 0) return false;
553
+ if (candidateFact.priority !== currentFact.priority)
554
+ return candidateFact.priority > currentFact.priority;
555
+ if (candidate.normalizedDistance !== current.normalizedDistance) {
556
+ return candidate.normalizedDistance < current.normalizedDistance;
557
+ }
558
+ return candidate.worldId < current.worldId || candidate.worldId === current.worldId && candidate.entityKey < current.entityKey;
559
+ }
560
+ function selectReflectionProbe(facts, primitiveCenter) {
561
+ let selected;
562
+ for (const fact of facts) {
563
+ if (!contains(fact, primitiveCenter)) continue;
564
+ const candidate = {
565
+ kind: "probe",
566
+ worldId: fact.worldId,
567
+ entityKey: fact.entityKey,
568
+ normalizedDistance: normalizedDistance(fact, primitiveCenter)
569
+ };
570
+ if (selected === void 0 || isBetter(candidate, selected, facts)) selected = candidate;
571
+ }
572
+ return selected ?? { kind: "skylight" };
573
+ }
574
+ function primitiveKey(worldId, entityKey) {
575
+ return `${worldId}:${entityKey}`;
576
+ }
577
+ var ReflectionProbeProjection = class {
578
+ revision = 0;
579
+ facts = [];
580
+ selected = /* @__PURE__ */ new Map();
581
+ signature = "";
582
+ scannedPrimitives = 0;
583
+ update(facts, primitives) {
584
+ const nextFacts = facts.slice().sort((a, b) => a.worldId - b.worldId || a.entityKey - b.entityKey);
585
+ const signature = JSON.stringify({ facts: nextFacts, primitives });
586
+ if (signature === this.signature) return this.snapshot();
587
+ this.signature = signature;
588
+ this.facts = nextFacts;
589
+ this.selected = /* @__PURE__ */ new Map();
590
+ for (const primitive of primitives) {
591
+ this.selected.set(
592
+ primitive.renderableKey ?? primitiveKey(primitive.worldId, primitive.entityKey),
593
+ selectReflectionProbe(nextFacts, primitive.center)
594
+ );
595
+ }
596
+ this.scannedPrimitives = primitives.length;
597
+ this.revision += 1;
598
+ return this.snapshot();
599
+ }
600
+ snapshot() {
601
+ return {
602
+ revision: this.revision,
603
+ facts: this.facts,
604
+ selected: this.selected,
605
+ scannedPrimitives: this.scannedPrimitives
606
+ };
607
+ }
608
+ selection(worldId, entityKey) {
609
+ return this.selected.get(primitiveKey(worldId, entityKey)) ?? { kind: "skylight" };
610
+ }
611
+ };
612
+
613
+ // src/scene/visibility/inspection.ts
614
+ var LOD_OCCLUSION_INSPECTION_SCHEMA = "forgeax::lod-occlusion-inspection::v2";
615
+ var LOD_OCCLUSION_INSPECTION_MAX_BYTES = 16 * 1024;
616
+ var MAX_INSPECTION_SAMPLES = 64;
617
+ function nonNegativeInteger(name, value) {
618
+ if (!Number.isInteger(value) || value < 0)
619
+ throw new Error(`${name} must be a non-negative integer`);
620
+ return value;
621
+ }
622
+ function copyError(error) {
623
+ return Object.freeze({
624
+ code: error.code,
625
+ expected: error.expected,
626
+ hint: error.hint,
627
+ ...error.detail === void 0 ? {} : { detail: Object.freeze({ ...error.detail }) }
628
+ });
629
+ }
630
+ function copyFallback(fallback) {
631
+ return fallback.active ? Object.freeze({ ...fallback, error: copyError(fallback.error) }) : Object.freeze({ active: false });
632
+ }
633
+ function copySamples(samples) {
634
+ return Object.freeze(
635
+ [...samples].sort((left, right) => left.primitiveSlot - right.primitiveSlot).slice(0, MAX_INSPECTION_SAMPLES).map(
636
+ (sample) => Object.freeze({
637
+ primitiveSlot: nonNegativeInteger("sample.primitiveSlot", sample.primitiveSlot),
638
+ level: nonNegativeInteger("sample.level", sample.level),
639
+ visible: sample.visible
640
+ })
641
+ )
642
+ );
643
+ }
644
+ function copyWorldAttribution(attribution) {
645
+ if (attribution === void 0) {
646
+ return Object.freeze({ status: "unavailable", reason: "projection-only" });
647
+ }
648
+ if (attribution.status === "same-submit") {
649
+ if (typeof attribution.submit.build !== "string" || attribution.submit.build.length === 0) {
650
+ throw new Error("world.attribution.submit.build must be a non-empty string");
651
+ }
652
+ nonNegativeInteger("world.attribution.submit.frameId", attribution.submit.frameId);
653
+ nonNegativeInteger(
654
+ "world.attribution.submit.deviceGeneration",
655
+ attribution.submit.deviceGeneration
656
+ );
657
+ return Object.freeze({
658
+ status: "same-submit",
659
+ submit: Object.freeze({ ...attribution.submit })
660
+ });
661
+ }
662
+ if (attribution.status !== "unavailable" || attribution.reason !== "projection-only") {
663
+ throw new Error("world.attribution must declare same-submit or projection-only");
664
+ }
665
+ return Object.freeze({ status: "unavailable", reason: "projection-only" });
666
+ }
667
+ function copyRow(row) {
668
+ for (const [name, value] of Object.entries({
669
+ generation: row.generation,
670
+ candidates: row.count.candidates,
671
+ visible: row.count.visible,
672
+ occluded: row.count.occluded,
673
+ median: row.queryLatencyUs.median,
674
+ p95: row.queryLatencyUs.p95,
675
+ last: row.queryLatencyUs.last,
676
+ pageUsed: row.pagePressure.used,
677
+ pageCapacity: row.pagePressure.capacity
678
+ }))
679
+ nonNegativeInteger(`inspection.${name}`, value);
680
+ if (row.view.cameraEntity < 0 || row.view.viewGeneration < 0 || row.slot.primitiveSlot < 0 || row.slot.slotGeneration < 0) {
681
+ throw new Error("inspection identity values must be non-negative");
682
+ }
683
+ if (row.pagePressure.used > row.pagePressure.capacity) {
684
+ throw new Error("inspection page pressure exceeds capacity");
685
+ }
686
+ return Object.freeze({
687
+ root: Object.freeze({ ...row.root }),
688
+ view: Object.freeze({ ...row.view }),
689
+ slot: Object.freeze({ ...row.slot }),
690
+ generation: row.generation,
691
+ count: Object.freeze({ ...row.count }),
692
+ lodHistogram: Object.freeze(
693
+ row.lodHistogram.map(
694
+ (histogram) => Object.freeze({
695
+ level: nonNegativeInteger("histogram.level", histogram.level),
696
+ count: nonNegativeInteger("histogram.count", histogram.count)
697
+ })
698
+ )
699
+ ),
700
+ queryLatencyUs: Object.freeze({ ...row.queryLatencyUs }),
701
+ pagePressure: Object.freeze({ ...row.pagePressure }),
702
+ fallback: copyFallback(row.fallback),
703
+ degradation: Object.freeze({ ...row.degradation }),
704
+ samples: copySamples(row.samples)
705
+ });
706
+ }
707
+ function copyWorlds(worlds, fallback) {
708
+ const source = worlds ?? [{ attachmentId: fallback.view.attachmentId, rows: [fallback] }];
709
+ return Object.freeze(
710
+ source.map(
711
+ (world) => Object.freeze({
712
+ attachmentId: world.attachmentId,
713
+ rows: Object.freeze(world.rows.map((row) => copyRow(row))),
714
+ attribution: copyWorldAttribution(world.attribution)
715
+ })
716
+ )
717
+ );
718
+ }
719
+ function inspectLodOcclusion(input) {
720
+ const row = copyRow(input);
721
+ const defaultBudget = createVisibilityBudget();
722
+ const budget = input.budget ?? {
723
+ configuredQueryBudget: defaultBudget.configuredQueryBudget,
724
+ effectiveQueryBudget: defaultBudget.effectiveQueryBudget,
725
+ settleSubmits: defaultBudget.settleSubmits,
726
+ retestSubmits: defaultBudget.retestSubmits,
727
+ expirySubmits: defaultBudget.expirySubmits
728
+ };
729
+ for (const [name, value] of Object.entries(budget))
730
+ nonNegativeInteger(`inspection.budget.${name}`, value);
731
+ const submit = input.submit ?? {
732
+ frameId: input.generation,
733
+ build: "unknown",
734
+ deviceGeneration: 0
735
+ };
736
+ nonNegativeInteger("inspection.submit.frameId", submit.frameId);
737
+ nonNegativeInteger("inspection.submit.deviceGeneration", submit.deviceGeneration);
738
+ if (typeof submit.build !== "string" || submit.build.length === 0) {
739
+ throw new Error("inspection.submit.build must be a non-empty string");
740
+ }
741
+ const worlds = copyWorlds(input.worlds, row);
742
+ for (const world of worlds) {
743
+ if (world.attribution.status === "same-submit" && (world.attribution.submit.frameId !== submit.frameId || world.attribution.submit.build !== submit.build || world.attribution.submit.deviceGeneration !== submit.deviceGeneration)) {
744
+ throw new Error("world attribution must reference the parent inspection submit");
745
+ }
746
+ }
747
+ const inspection = Object.freeze({
748
+ schema: LOD_OCCLUSION_INSPECTION_SCHEMA,
749
+ ...row,
750
+ submit: Object.freeze({ ...submit }),
751
+ budget: Object.freeze({ ...budget }),
752
+ worlds
753
+ });
754
+ if (JSON.stringify(inspection).length > LOD_OCCLUSION_INSPECTION_MAX_BYTES) {
755
+ throw new Error(`LOD occlusion inspection exceeds ${LOD_OCCLUSION_INSPECTION_MAX_BYTES} bytes`);
756
+ }
757
+ return inspection;
758
+ }
759
+ function serializeLodOcclusionInspection(inspection) {
760
+ const serialized = JSON.stringify(inspection);
761
+ if (serialized.length > LOD_OCCLUSION_INSPECTION_MAX_BYTES) {
762
+ throw new Error(`LOD occlusion inspection exceeds ${LOD_OCCLUSION_INSPECTION_MAX_BYTES} bytes`);
763
+ }
764
+ return serialized;
765
+ }
766
+ function consumeLodOcclusionInspection(inspection) {
767
+ if (!inspection.fallback.active) return { action: "none" };
768
+ const { reason, error } = inspection.fallback;
769
+ const action = error.code.startsWith("asset-") || reason === "producer-failed" ? "rebuild" : reason === "query-failed" || reason === "page-exhausted" || reason === "device-loss" ? "retry" : "cold-cook";
770
+ return { action, sourceKey: inspection.root.sourceKey, reason };
771
+ }
772
+ var SSR_FORMAT_PROFILE = "r32float-mip-sampled-storage";
773
+ var SSR_FORMAT_STAGES = Object.freeze([
774
+ "texture-create",
775
+ "mip-view",
776
+ "sampled-storage-bind-group",
777
+ "pipeline-bind",
778
+ "finish",
779
+ "submit",
780
+ "completion",
781
+ "readback"
782
+ ]);
783
+ var ZERO_WORK = Object.freeze({
784
+ attachmentCount: 0,
785
+ passCount: 0,
786
+ bindingCount: 0,
787
+ resourceCount: 0,
788
+ historyCount: 0,
789
+ temporalDemand: 0
790
+ });
791
+ var ADMITTED_WORK = Object.freeze({
792
+ attachmentCount: 1,
793
+ passCount: 1,
794
+ bindingCount: 1,
795
+ resourceCount: 1,
796
+ historyCount: 0,
797
+ temporalDemand: 0
798
+ });
799
+ var ZERO_BUDGET = Object.freeze({
800
+ probeExecutions: 0,
801
+ resetCount: 0,
802
+ rebuildCount: 0
803
+ });
804
+ var ADMITTED_BUDGET = Object.freeze({
805
+ probeExecutions: 1,
806
+ resetCount: 0,
807
+ rebuildCount: 0
808
+ });
809
+ function identityFieldMismatch(expected, actual) {
810
+ for (const field of ["sourceHead", "sourceTree", "lockSha256", "buildSha256"]) {
811
+ if (expected[field] !== actual[field]) return field;
812
+ }
813
+ return void 0;
814
+ }
815
+ function blocked(identity, failure2, generation = 0) {
816
+ return Object.freeze({
817
+ status: "fallback-only",
818
+ identity,
819
+ generation,
820
+ work: ZERO_WORK,
821
+ budget: ZERO_BUDGET,
822
+ failure: failure2
823
+ });
824
+ }
825
+ function failure(code, owner, hint, detail = {}) {
826
+ const action = recoveryActionFor(code);
827
+ return Object.freeze({
828
+ code,
829
+ expected: "all producer, format, and temporal receipts share one admitted identity",
830
+ hint,
831
+ detail: Object.freeze({ owner, action, ...detail })
832
+ });
833
+ }
834
+ function recoveryActionFor(code) {
835
+ switch (code) {
836
+ case "ssr-reflection-fallback-unavailable":
837
+ case "ssr-receipt-identity-mismatch":
838
+ return "rebuild";
839
+ case "ssr-not-requested":
840
+ case "ssr-format-unavailable":
841
+ case "ssr-temporal-unavailable":
842
+ case "ssr-receipt-stale":
843
+ return "retry";
844
+ }
845
+ }
846
+ function receiptFailure(input, receipt, owner) {
847
+ const field = identityFieldMismatch(input.identity, receipt.identity);
848
+ if (field === void 0) return void 0;
849
+ return blocked(
850
+ input.identity,
851
+ failure("ssr-receipt-identity-mismatch", owner, "rebuild the owner receipt for this identity", {
852
+ identityField: field
853
+ })
854
+ );
855
+ }
856
+ function validFallback(receipt) {
857
+ return receipt !== void 0 && receipt.candidateVisible === false && Number.isFinite(receipt.coverage) && receipt.coverage >= 0 && receipt.coverage <= 1 && (receipt.sourceKey === void 0 || receipt.sourceKey.length > 0) && (receipt.extent === void 0 || receipt.extent.length === 3 && receipt.extent.every((value) => Number.isFinite(value) && value > 0)) && Number.isInteger(receipt.sourceGeneration) && receipt.sourceGeneration >= 0 && Number.isInteger(receipt.projectionGeneration) && receipt.projectionGeneration >= 0 && Number.isInteger(receipt.deviceGeneration) && receipt.deviceGeneration >= 0 && receipt.brdfSignature === "standard-pbr-ibl-v1" && (receipt.source === "probe" && (receipt.state === "active" || receipt.state === "lkg") || receipt.source === "skylight" && (receipt.state === "active" || receipt.state === "lkg") || receipt.source === "neutral" && receipt.state === "neutral");
858
+ }
859
+ function validFormat(receipt) {
860
+ if (receipt?.profile !== SSR_FORMAT_PROFILE || receipt.verdict !== "admitted" || receipt.evidence !== "real" || !Number.isInteger(receipt.deviceGeneration) || receipt.deviceGeneration < 0) {
861
+ return false;
862
+ }
863
+ if (!SSR_FORMAT_STAGES.every(
864
+ (stage) => receipt.stages.some((entry) => entry.stage === stage && entry.verdict === "admitted")
865
+ )) {
866
+ return false;
867
+ }
868
+ return validateR32FloatReceipt(receipt).ok;
869
+ }
870
+ function validTemporal(receipt) {
871
+ return receipt?.successfulSubmit === true && Number.isInteger(receipt.generation) && receipt.generation >= 0;
872
+ }
873
+ function admitSsrM0(input) {
874
+ if (!input.requested) {
875
+ return blocked(
876
+ input.identity,
877
+ failure("ssr-not-requested", "consumer", "request SSR before evaluating M0 admission")
878
+ );
879
+ }
880
+ if (input.reflectionFallback === void 0) {
881
+ return blocked(
882
+ input.identity,
883
+ failure("ssr-reflection-fallback-unavailable", "producer", "use LKG, Skylight, or neutral")
884
+ );
885
+ }
886
+ const fallbackIdentityFailure = receiptFailure(input, input.reflectionFallback, "producer");
887
+ if (fallbackIdentityFailure !== void 0) return fallbackIdentityFailure;
888
+ if (!validFallback(input.reflectionFallback)) {
889
+ return blocked(
890
+ input.identity,
891
+ failure(
892
+ "ssr-reflection-fallback-unavailable",
893
+ "producer",
894
+ "inspect and rebuild the producer receipt"
895
+ ),
896
+ input.reflectionFallback.projectionGeneration
897
+ );
898
+ }
899
+ if (input.format === void 0) {
900
+ return blocked(
901
+ input.identity,
902
+ failure("ssr-format-unavailable", "format", "probe the exact format profile for this device"),
903
+ input.reflectionFallback.projectionGeneration
904
+ );
905
+ }
906
+ const formatIdentityFailure = receiptFailure(input, input.format, "format");
907
+ if (formatIdentityFailure !== void 0) return formatIdentityFailure;
908
+ if (!validFormat(input.format)) {
909
+ return blocked(
910
+ input.identity,
911
+ failure("ssr-format-unavailable", "format", "complete the full r32float profile probe"),
912
+ input.reflectionFallback.projectionGeneration
913
+ );
914
+ }
915
+ if (input.temporal === void 0) {
916
+ return blocked(
917
+ input.identity,
918
+ failure(
919
+ "ssr-temporal-unavailable",
920
+ "temporal",
921
+ "submit the matching temporal producer receipt"
922
+ ),
923
+ input.reflectionFallback.projectionGeneration
924
+ );
925
+ }
926
+ const temporalIdentityFailure = receiptFailure(input, input.temporal, "temporal");
927
+ if (temporalIdentityFailure !== void 0) return temporalIdentityFailure;
928
+ if (!validTemporal(input.temporal)) {
929
+ return blocked(
930
+ input.identity,
931
+ failure("ssr-temporal-unavailable", "temporal", "inspect and rebuild the temporal receipt"),
932
+ input.reflectionFallback.projectionGeneration
933
+ );
934
+ }
935
+ if (input.previousGeneration !== void 0 && input.previousGeneration !== input.reflectionFallback.projectionGeneration) {
936
+ return blocked(
937
+ input.identity,
938
+ failure(
939
+ "ssr-receipt-stale",
940
+ "consumer",
941
+ "discard stale completion and reinspect the owners",
942
+ {
943
+ generation: input.reflectionFallback.projectionGeneration
944
+ }
945
+ ),
946
+ input.reflectionFallback.projectionGeneration
947
+ );
948
+ }
949
+ return Object.freeze({
950
+ status: "admitted",
951
+ identity: input.identity,
952
+ generation: input.reflectionFallback.projectionGeneration,
953
+ work: ADMITTED_WORK,
954
+ budget: ADMITTED_BUDGET
955
+ });
956
+ }
957
+ function projectSsrDependencies(input) {
958
+ const identity = input.identity;
959
+ const reflectionFallback = identity === void 0 || input.reflectionFallback?.identity === void 0 ? void 0 : input.reflectionFallback;
960
+ const format = identity === void 0 || input.format === void 0 ? void 0 : { ...input.format, identity };
961
+ const temporal = identity === void 0 || input.temporal === void 0 ? void 0 : { identity, ...input.temporal };
962
+ const admission = identity === void 0 ? blocked(
963
+ void 0,
964
+ failure(
965
+ input.requested ? "ssr-receipt-identity-mismatch" : "ssr-not-requested",
966
+ "consumer",
967
+ input.requested ? "bind the exact source, tree, lock, and build identity before admission" : "request SSR before evaluating M0 admission",
968
+ input.requested ? { identityField: "sourceHead" } : {}
969
+ )
970
+ ) : admitSsrM0({
971
+ requested: input.requested,
972
+ identity,
973
+ ...reflectionFallback === void 0 ? {} : { reflectionFallback },
974
+ ...format === void 0 ? {} : { format },
975
+ ...temporal === void 0 ? {} : { temporal },
976
+ ...input.previousGeneration === void 0 ? {} : { previousGeneration: input.previousGeneration }
977
+ });
978
+ return Object.freeze({
979
+ status: admission.status,
980
+ identity,
981
+ requested: input.requested,
982
+ reflectionFallback: input.reflectionFallback,
983
+ format,
984
+ temporal,
985
+ admission,
986
+ work: admission.work,
987
+ budget: admission.budget,
988
+ failure: admission.failure
989
+ });
990
+ }
991
+ function zeroSsrAdmissionWork() {
992
+ return ZERO_WORK;
993
+ }
994
+ function resolveSsrAdmissionGeneration(previousGeneration, nextGeneration) {
995
+ return {
996
+ changed: previousGeneration !== void 0 && nextGeneration !== void 0 && previousGeneration !== nextGeneration,
997
+ generation: nextGeneration
998
+ };
999
+ }
1000
+
1001
+ export { DEFAULT_REFLECTION_PROBE_LIMITS, LOD_OCCLUSION_INSPECTION_MAX_BYTES, LOD_OCCLUSION_INSPECTION_SCHEMA, ReflectionProbeProjection, SSR_FORMAT_PROFILE, SSR_FORMAT_STAGES, admitPointsLines, admitReflectionProbe, admitSsrM0, advanceProbeFilter, boxProjectReflectionDirection, buildCubeCameraFaceViews, buildReflectionProbeTable, commitProbeFilterStep, consumeLodOcclusionInspection, createProbeFilterState, deriveReflectionFallbackProjection, estimateReflectionProbeBytes, inspectLodOcclusion, inspectPointShadow, inspectReflectionFallback, inspectVolumetricFog, probeFilterIsSteady, projectSsrDependencies, reflectionFallbackCoverage, reflectionFallbackProjectionSignature, reflectionFallbackSourceKey, reflectionProbeTableBytes, resolveReflectionFallbackSource, resolveSsrAdmissionGeneration, selectReflectionProbe, serializeLodOcclusionInspection, validateReflectionProbeInput, zeroSsrAdmissionWork };
1002
+ //# sourceMappingURL=chunk-UQYS7FRM.mjs.map
1003
+ //# sourceMappingURL=chunk-UQYS7FRM.mjs.map