@forgeax/engine-render 0.1.27 → 0.1.29

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 (655) hide show
  1. package/README.md +842 -124
  2. package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
  3. package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
  4. package/dist/assembly/dynamic-geometry-host.d.ts +52 -0
  5. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -0
  6. package/dist/assembly/dynamic-geometry-runtime.d.ts +20 -0
  7. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -0
  8. package/dist/assembly/factory.d.ts +3 -1
  9. package/dist/assembly/factory.d.ts.map +1 -1
  10. package/dist/assembly/gpu-driven-owner.d.ts +10 -0
  11. package/dist/assembly/gpu-driven-owner.d.ts.map +1 -0
  12. package/dist/assembly/host-contract.d.ts +19 -0
  13. package/dist/assembly/host-contract.d.ts.map +1 -1
  14. package/dist/assembly/material/assembly.d.ts +7 -0
  15. package/dist/assembly/material/assembly.d.ts.map +1 -1
  16. package/dist/assembly/material-shader-policy.d.ts +3 -1
  17. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  18. package/dist/assembly/recovery/failure-location.d.ts +12 -0
  19. package/dist/assembly/recovery/failure-location.d.ts.map +1 -0
  20. package/dist/assembly/recovery/renderer-recover.d.ts +6 -4
  21. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  22. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  23. package/dist/assembly/renderer-feature-inspection.d.ts +5 -0
  24. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -0
  25. package/dist/assembly/renderer-frame-transaction.d.ts +19 -0
  26. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  27. package/dist/assembly/renderer-helpers.d.ts +3 -0
  28. package/dist/assembly/renderer-helpers.d.ts.map +1 -1
  29. package/dist/assembly/renderer-inspection.d.ts +4 -0
  30. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  31. package/dist/assembly/shader-prewarm-policy.d.ts +6 -0
  32. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
  33. package/dist/assembly/skin-palette-owner.d.ts +8 -0
  34. package/dist/assembly/skin-palette-owner.d.ts.map +1 -0
  35. package/dist/assembly/ssr-shader-prewarm.d.ts +6 -0
  36. package/dist/assembly/ssr-shader-prewarm.d.ts.map +1 -0
  37. package/dist/assembly/webgpu-device-loss.d.ts +15 -0
  38. package/dist/assembly/webgpu-device-loss.d.ts.map +1 -0
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +38 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -0
  41. package/dist/assembly/webgpu-ready-mipmap.d.ts +11 -0
  42. package/dist/assembly/webgpu-ready-mipmap.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +7 -3
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts +10 -0
  46. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -0
  47. package/dist/assembly/webgpu-renderer-contract.d.ts +62 -0
  48. package/dist/assembly/webgpu-renderer-contract.d.ts.map +1 -0
  49. package/dist/assembly/webgpu-renderer-guards.d.ts +9 -0
  50. package/dist/assembly/webgpu-renderer-guards.d.ts.map +1 -0
  51. package/dist/assembly/webgpu-renderer-observation.d.ts +6 -0
  52. package/dist/assembly/webgpu-renderer-observation.d.ts.map +1 -0
  53. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts +12 -0
  54. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts.map +1 -0
  55. package/dist/assembly/webgpu-renderer.d.ts +7 -141
  56. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  57. package/dist/assembly/webgpu-vertex-layouts.d.ts +28 -84
  58. package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
  59. package/dist/authoring.mjs +3 -3
  60. package/dist/{chunk-ADHHVYLW.mjs → chunk-33XZFTQU.mjs} +245 -39
  61. package/dist/chunk-33XZFTQU.mjs.map +1 -0
  62. package/dist/{chunk-GF523LHF.mjs → chunk-BLXGONR2.mjs} +30 -12
  63. package/dist/chunk-BLXGONR2.mjs.map +1 -0
  64. package/dist/{chunk-KM2NOX2I.mjs → chunk-BQVQOQJH.mjs} +958 -254
  65. package/dist/chunk-BQVQOQJH.mjs.map +1 -0
  66. package/dist/{chunk-HKXTW355.mjs → chunk-BTWH7BP4.mjs} +386 -17
  67. package/dist/chunk-BTWH7BP4.mjs.map +1 -0
  68. package/dist/{chunk-TMIASV2N.mjs → chunk-FUODTTIA.mjs} +3934 -676
  69. package/dist/chunk-FUODTTIA.mjs.map +1 -0
  70. package/dist/{chunk-FJ6P52EE.mjs → chunk-ILQ5MEZF.mjs} +3 -17
  71. package/dist/chunk-ILQ5MEZF.mjs.map +1 -0
  72. package/dist/{chunk-E34VL5VI.mjs → chunk-JQTSEI3Z.mjs} +3 -3
  73. package/dist/{chunk-E34VL5VI.mjs.map → chunk-JQTSEI3Z.mjs.map} +1 -1
  74. package/dist/{chunk-GE3SDD72.mjs → chunk-NICXSHAT.mjs} +16 -38
  75. package/dist/chunk-NICXSHAT.mjs.map +1 -0
  76. package/dist/{chunk-ZZ4YQ474.mjs → chunk-NRNXBLIJ.mjs} +577 -7
  77. package/dist/chunk-NRNXBLIJ.mjs.map +1 -0
  78. package/dist/{chunk-JDWARUOI.mjs → chunk-PA5DRJNI.mjs} +17 -3
  79. package/dist/chunk-PA5DRJNI.mjs.map +1 -0
  80. package/dist/{chunk-XDP6XE5V.mjs → chunk-S4DNKQYQ.mjs} +1118 -446
  81. package/dist/chunk-S4DNKQYQ.mjs.map +1 -0
  82. package/dist/components/camera.d.ts +62 -2
  83. package/dist/components/camera.d.ts.map +1 -1
  84. package/dist/components/index.d.ts +1 -0
  85. package/dist/components/index.d.ts.map +1 -1
  86. package/dist/components/instances.d.ts +6 -20
  87. package/dist/components/instances.d.ts.map +1 -1
  88. package/dist/components/scene-instance.d.ts +2 -1
  89. package/dist/components/scene-instance.d.ts.map +1 -1
  90. package/dist/components/screen-space-reflection.d.ts +14 -0
  91. package/dist/components/screen-space-reflection.d.ts.map +1 -0
  92. package/dist/construct-renderer.mjs +13805 -7186
  93. package/dist/construct-renderer.mjs.map +1 -1
  94. package/dist/device/gpu-residency.d.ts +11 -17
  95. package/dist/device/gpu-residency.d.ts.map +1 -1
  96. package/dist/device/mesh-residency-lifetime.d.ts +21 -0
  97. package/dist/device/mesh-residency-lifetime.d.ts.map +1 -0
  98. package/dist/dynamic-geometry.d.ts +125 -0
  99. package/dist/dynamic-geometry.d.ts.map +1 -0
  100. package/dist/environment/background.d.ts +6 -0
  101. package/dist/environment/background.d.ts.map +1 -0
  102. package/dist/errors/gpu-driven.d.ts +6 -3
  103. package/dist/errors/gpu-driven.d.ts.map +1 -1
  104. package/dist/errors/render.d.ts +7 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/extract/camera.d.ts.map +1 -1
  107. package/dist/extract/gpu-driven.d.ts +33 -3
  108. package/dist/extract/gpu-driven.d.ts.map +1 -1
  109. package/dist/features/host.d.ts +23 -1
  110. package/dist/features/host.d.ts.map +1 -1
  111. package/dist/features/noise-texture.d.ts +17 -0
  112. package/dist/features/noise-texture.d.ts.map +1 -0
  113. package/dist/features/plan.d.ts +83 -2
  114. package/dist/features/plan.d.ts.map +1 -1
  115. package/dist/features/prepared-gpu-work.d.ts +37 -4
  116. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  117. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  118. package/dist/features/prepared-graphics.d.ts +5 -0
  119. package/dist/features/prepared-graphics.d.ts.map +1 -1
  120. package/dist/features/render-graph-compute.d.ts +5 -3
  121. package/dist/features/render-graph-compute.d.ts.map +1 -1
  122. package/dist/features/render-graph-contribution.d.ts +11 -3
  123. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  124. package/dist/features/render-graph-raster.d.ts +19 -3
  125. package/dist/features/render-graph-raster.d.ts.map +1 -1
  126. package/dist/features/types.d.ts +11 -0
  127. package/dist/features/types.d.ts.map +1 -1
  128. package/dist/fullscreen-post-process-pass.d.ts +2 -0
  129. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  130. package/dist/gpu-driven/batch-topology.d.ts +34 -1
  131. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  132. package/dist/gpu-driven/pbr-program.d.ts +10 -0
  133. package/dist/gpu-driven/pbr-program.d.ts.map +1 -0
  134. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  135. package/dist/gpu-driven/production-raster.d.ts +144 -23
  136. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  137. package/dist/gpu-driven/shadow-views.d.ts +126 -0
  138. package/dist/gpu-driven/shadow-views.d.ts.map +1 -0
  139. package/dist/gpu-driven/view-gpu.d.ts +18 -2
  140. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  141. package/dist/gpu-scene-schema.d.ts +2 -8
  142. package/dist/gpu-scene-schema.d.ts.map +1 -1
  143. package/dist/gpu-scene.d.ts +14 -0
  144. package/dist/gpu-scene.d.ts.map +1 -1
  145. package/dist/gpu-texture-usage.d.ts +1 -0
  146. package/dist/gpu-texture-usage.d.ts.map +1 -1
  147. package/dist/hdrp-buffers.d.ts +6 -0
  148. package/dist/hdrp-buffers.d.ts.map +1 -1
  149. package/dist/ibl/frame-resources.d.ts +8 -0
  150. package/dist/ibl/frame-resources.d.ts.map +1 -0
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +21 -8
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +8 -7
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +164 -0
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instances-derived-bounds.d.ts +11 -0
  159. package/dist/instances-derived-bounds.d.ts.map +1 -1
  160. package/dist/instances.d.ts +89 -44
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.d.ts +3 -0
  163. package/dist/internal.d.ts.map +1 -1
  164. package/dist/internal.mjs +118 -10
  165. package/dist/internal.mjs.map +1 -1
  166. package/dist/lifecycle.d.ts +2 -1
  167. package/dist/lifecycle.d.ts.map +1 -1
  168. package/dist/material-row.d.ts +5 -0
  169. package/dist/material-row.d.ts.map +1 -0
  170. package/dist/materials.d.ts +15 -0
  171. package/dist/materials.d.ts.map +1 -1
  172. package/dist/pbr-pipeline.d.ts +21 -5
  173. package/dist/pbr-pipeline.d.ts.map +1 -1
  174. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  175. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts +12 -0
  176. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts.map +1 -0
  177. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts +70 -0
  178. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts.map +1 -0
  179. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts +75 -0
  180. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts.map +1 -0
  181. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts +111 -0
  182. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts.map +1 -0
  183. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts +16 -0
  184. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts.map +1 -0
  185. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts +14 -0
  186. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts.map +1 -0
  187. package/dist/pipeline/standard-output/auto-exposure/state.d.ts +46 -0
  188. package/dist/pipeline/standard-output/auto-exposure/state.d.ts.map +1 -0
  189. package/dist/pipeline/standard-output/color-transform.d.ts +27 -0
  190. package/dist/pipeline/standard-output/color-transform.d.ts.map +1 -0
  191. package/dist/pipeline/standard-output/graph.d.ts +15 -0
  192. package/dist/pipeline/standard-output/graph.d.ts.map +1 -0
  193. package/dist/pipeline/standard-output/lut-admission.d.ts +29 -0
  194. package/dist/pipeline/standard-output/lut-admission.d.ts.map +1 -0
  195. package/dist/pipeline/standard-output/lut-gpu.d.ts +48 -0
  196. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -0
  197. package/dist/pipeline/standard-output/lut-state.d.ts +68 -0
  198. package/dist/pipeline/standard-output/lut-state.d.ts.map +1 -0
  199. package/dist/pipeline/standard-output/resources.d.ts +10 -0
  200. package/dist/pipeline/standard-output/resources.d.ts.map +1 -0
  201. package/dist/pipeline/standard-output/types.d.ts +39 -0
  202. package/dist/pipeline/standard-output/types.d.ts.map +1 -0
  203. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  204. package/dist/pipeline/standard-post.d.ts +2 -2
  205. package/dist/pipeline/standard-post.d.ts.map +1 -1
  206. package/dist/pipeline-builder.d.ts +2 -1
  207. package/dist/pipeline-builder.d.ts.map +1 -1
  208. package/dist/pipeline-spec-types.d.ts +4 -0
  209. package/dist/pipeline-spec-types.d.ts.map +1 -1
  210. package/dist/pipeline-spec.d.ts +1 -9
  211. package/dist/pipeline-spec.d.ts.map +1 -1
  212. package/dist/points-lines/standard-owner.d.ts +1 -1
  213. package/dist/points-lines/standard-owner.d.ts.map +1 -1
  214. package/dist/prepare/prepared-graphics-resolver.d.ts +6 -1
  215. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  216. package/dist/record/dynamic-geometry-consumption.d.ts +15 -0
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -0
  218. package/dist/record/frame-lighting.d.ts +3 -3
  219. package/dist/record/frame-lighting.d.ts.map +1 -1
  220. package/dist/record/frame-snapshot.d.ts +106 -5
  221. package/dist/record/frame-snapshot.d.ts.map +1 -1
  222. package/dist/record/frame-targets.d.ts.map +1 -1
  223. package/dist/record/frame.d.ts +39 -4
  224. package/dist/record/frame.d.ts.map +1 -1
  225. package/dist/record/main-pass-geometry.d.ts +7 -8
  226. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  227. package/dist/record/main-pass-material.d.ts +38 -1
  228. package/dist/record/main-pass-material.d.ts.map +1 -1
  229. package/dist/record/main-pass-sprite-draws.d.ts +2 -10
  230. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  231. package/dist/record/main-pass.d.ts +12 -2
  232. package/dist/record/main-pass.d.ts.map +1 -1
  233. package/dist/record/mesh-ssbo.d.ts +15 -6
  234. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  235. package/dist/record/prepared-material-bindings.d.ts +19 -0
  236. package/dist/record/prepared-material-bindings.d.ts.map +1 -0
  237. package/dist/record/recovery-pipeline.d.ts +2 -9
  238. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  239. package/dist/record/render-context.d.ts +76 -26
  240. package/dist/record/render-context.d.ts.map +1 -1
  241. package/dist/record/shadow-pass.d.ts +62 -7
  242. package/dist/record/shadow-pass.d.ts.map +1 -1
  243. package/dist/record/skybox-post-pass.d.ts +1 -1
  244. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  245. package/dist/record/typed-frame-graph.d.ts +35 -7
  246. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  247. package/dist/record/view-ubo.d.ts +1 -0
  248. package/dist/record/view-ubo.d.ts.map +1 -1
  249. package/dist/recovery/render-system-candidate.d.ts +10 -2
  250. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  251. package/dist/recovery/render-system-roots.d.ts +11 -0
  252. package/dist/recovery/render-system-roots.d.ts.map +1 -0
  253. package/dist/recovery/types.d.ts +76 -0
  254. package/dist/recovery/types.d.ts.map +1 -0
  255. package/dist/reflection/record-owner.d.ts +0 -2
  256. package/dist/reflection/record-owner.d.ts.map +1 -1
  257. package/dist/render-contract.d.ts +185 -30
  258. package/dist/render-contract.d.ts.map +1 -1
  259. package/dist/render-graph-primitives.d.ts +1 -0
  260. package/dist/render-graph-primitives.d.ts.map +1 -1
  261. package/dist/render-pipeline.d.ts +64 -5
  262. package/dist/render-pipeline.d.ts.map +1 -1
  263. package/dist/render-system-extract-tail.d.ts +7 -5
  264. package/dist/render-system-extract-tail.d.ts.map +1 -1
  265. package/dist/render-system-extract.d.ts +101 -41
  266. package/dist/render-system-extract.d.ts.map +1 -1
  267. package/dist/render-system-projections.d.ts +22 -0
  268. package/dist/render-system-projections.d.ts.map +1 -0
  269. package/dist/render-system.d.ts +34 -77
  270. package/dist/render-system.d.ts.map +1 -1
  271. package/dist/scene/render-scene-types.d.ts +14 -7
  272. package/dist/scene/render-scene-types.d.ts.map +1 -1
  273. package/dist/scene/render-scene.d.ts +29 -11
  274. package/dist/scene/render-scene.d.ts.map +1 -1
  275. package/dist/scene/shadow-visibility.d.ts +5 -0
  276. package/dist/scene/shadow-visibility.d.ts.map +1 -0
  277. package/dist/ssr/admission.d.ts +70 -1
  278. package/dist/ssr/admission.d.ts.map +1 -1
  279. package/dist/ssr/compose.d.ts +13 -0
  280. package/dist/ssr/compose.d.ts.map +1 -0
  281. package/dist/ssr/errors.d.ts +35 -0
  282. package/dist/ssr/errors.d.ts.map +1 -1
  283. package/dist/ssr/graph.d.ts +60 -0
  284. package/dist/ssr/graph.d.ts.map +1 -0
  285. package/dist/ssr/history.d.ts +97 -0
  286. package/dist/ssr/history.d.ts.map +1 -0
  287. package/dist/ssr/hiz.d.ts +37 -0
  288. package/dist/ssr/hiz.d.ts.map +1 -0
  289. package/dist/ssr/inspection.d.ts +42 -0
  290. package/dist/ssr/inspection.d.ts.map +1 -0
  291. package/dist/ssr/resources.d.ts +58 -0
  292. package/dist/ssr/resources.d.ts.map +1 -0
  293. package/dist/ssr/temporal.d.ts +38 -0
  294. package/dist/ssr/temporal.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts +32 -10
  296. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  297. package/dist/systems/skin-palette-types.d.ts +15 -0
  298. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  299. package/dist/systems/transparent-dispatch.d.ts +9 -0
  300. package/dist/systems/transparent-dispatch.d.ts.map +1 -0
  301. package/dist/targets/material-source.d.ts +7 -0
  302. package/dist/targets/material-source.d.ts.map +1 -1
  303. package/dist/temporal/frame-coordinator.d.ts +7 -0
  304. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  305. package/dist/temporal/gpu.d.ts +8 -0
  306. package/dist/temporal/gpu.d.ts.map +1 -1
  307. package/dist/temporal/history.d.ts.map +1 -1
  308. package/dist/temporal/index.mjs +6 -6
  309. package/dist/temporal/inspection.d.ts.map +1 -1
  310. package/dist/temporal/standard-scene-data.d.ts +2 -1
  311. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  312. package/dist/temporal/temporal-view.d.ts +2 -0
  313. package/dist/temporal/temporal-view.d.ts.map +1 -1
  314. package/dist/typed-render-graph-primitives.d.ts +35 -1
  315. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  316. package/dist/typed-shadow-passes.d.ts +3 -1
  317. package/dist/typed-shadow-passes.d.ts.map +1 -1
  318. package/dist/volume/temporal.d.ts +6 -0
  319. package/dist/volume/temporal.d.ts.map +1 -1
  320. package/package.json +21 -20
  321. package/src/__tests__/auto-exposure-gpu-evidence.ts +291 -0
  322. package/src/__tests__/auto-exposure-inspection.unit.test.ts +80 -0
  323. package/src/__tests__/auto-exposure-transaction.integration.test.ts +99 -0
  324. package/src/__tests__/auto-exposure.browser.test.ts +33 -0
  325. package/src/__tests__/auto-exposure.dawn.test.ts +33 -0
  326. package/src/__tests__/detached-inspection.integration.test.ts +5 -0
  327. package/src/__tests__/device-scope-lifecycle.unit.test.ts +18 -0
  328. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +18 -0
  329. package/src/__tests__/docs-gate-green.unit.test.ts +3 -3
  330. package/src/__tests__/dynamic-geometry-host.unit.test.ts +1123 -0
  331. package/src/__tests__/dynamic-geometry.unit.test.ts +233 -0
  332. package/src/__tests__/factory-contract.integration.test.ts +73 -22
  333. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +19 -0
  334. package/src/__tests__/feature-depth-input.dawn.test.ts +121 -0
  335. package/src/__tests__/feature-noise.unit.test.ts +38 -0
  336. package/src/__tests__/fixtures/taa-resolve-pinned-baseline.wgsl +301 -0
  337. package/src/__tests__/frame-camera-selection.unit.test.ts +131 -0
  338. package/src/__tests__/frame-plan-contract.unit.test.ts +24 -0
  339. package/src/__tests__/frame-targets.unit.test.ts +24 -0
  340. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +3 -0
  341. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +79 -0
  342. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +287 -6
  343. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +122 -142
  344. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +10 -1
  345. package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +264 -0
  346. package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +349 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1417 -0
  348. package/src/__tests__/gpu-driven-pbr.integration.test.ts +21 -0
  349. package/src/__tests__/gpu-driven-production-fixture.ts +96 -0
  350. package/src/__tests__/gpu-driven-production.integration.test.ts +1075 -93
  351. package/src/__tests__/gpu-driven-scaling.unit.test.ts +1 -3
  352. package/src/__tests__/gpu-driven-shadow-views.browser.test.ts +63 -0
  353. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +294 -0
  354. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +97 -0
  355. package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +168 -0
  356. package/src/__tests__/gpu-driven-skin-contract.test-d.ts +11 -0
  357. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +72 -20
  358. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +30 -9
  359. package/src/__tests__/gpu-driven-view.unit.test.ts +159 -52
  360. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -1
  361. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +42 -0
  362. package/src/__tests__/gpu-scene-render-graph-gpu.ts +19 -5
  363. package/src/__tests__/gpu-scene.dawn.test.ts +40 -13
  364. package/src/__tests__/gpu-scene.unit.test.ts +559 -33
  365. package/src/__tests__/instances-culling.integration.test.ts +36 -10
  366. package/src/__tests__/instances-derived-bounds.unit.test.ts +54 -0
  367. package/src/__tests__/instances-store.unit.test.ts +242 -39
  368. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +6 -0
  369. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +13 -16
  370. package/src/__tests__/lut-lkg-transaction.integration.test.ts +122 -0
  371. package/src/__tests__/material-contract-inventory.unit.test.ts +5 -6
  372. package/src/__tests__/material-dispatch-shader-id.unit.test.ts +51 -0
  373. package/src/__tests__/material-lane-selection.unit.test.ts +60 -0
  374. package/src/__tests__/material-numeric-upload.unit.test.ts +53 -0
  375. package/src/__tests__/material-texture-handles.unit.test.ts +18 -0
  376. package/src/__tests__/material-texture-source.unit.test.ts +87 -0
  377. package/src/__tests__/materials-authoring-validation.unit.test.ts +41 -0
  378. package/src/__tests__/materials-standard-contract.unit.test.ts +52 -2
  379. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
  380. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +53 -0
  381. package/src/__tests__/normal-fallback.dawn.test.ts +122 -0
  382. package/src/__tests__/particle-material-input-layout.unit.test.ts +104 -0
  383. package/src/__tests__/physical-clearcoat.integration.test.ts +37 -3
  384. package/src/__tests__/pipeline-texture-specialization.unit.test.ts +138 -0
  385. package/src/__tests__/point-shadow-inspection.unit.test.ts +2 -0
  386. package/src/__tests__/prepared-gpu-driven-pbr-contract.test-d.ts +31 -0
  387. package/src/__tests__/prepared-gpu-driven-pbr-contract.unit.test.ts +39 -0
  388. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +35 -4
  389. package/src/__tests__/prepared-graphics-capability.unit.test.ts +21 -0
  390. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +6 -2
  391. package/src/__tests__/profiler-phase-catalog.test.ts +5 -0
  392. package/src/__tests__/public-surface.test-d.ts +3 -0
  393. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +30 -12
  394. package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +104 -0
  395. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +2 -1
  396. package/src/__tests__/render-error-code-owner.test-d.ts +4 -0
  397. package/src/__tests__/render-error-detail-ssot.test-d.ts +22 -0
  398. package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
  399. package/src/__tests__/render-feature-gpu-work.integration.test.ts +285 -2
  400. package/src/__tests__/render-feature-plan.unit.test.ts +245 -0
  401. package/src/__tests__/render-feature-shadow-order.unit.test.ts +228 -0
  402. package/src/__tests__/render-feature-zero-work.unit.test.ts +35 -1
  403. package/src/__tests__/render-graph-fallback.integration.test.ts +2 -2
  404. package/src/__tests__/render-owner-cohesion.unit.test.ts +55 -0
  405. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +426 -0
  406. package/src/__tests__/render-scene-projection.unit.test.ts +914 -23
  407. package/src/__tests__/render-scene-resource-updates.integration.test.ts +214 -0
  408. package/src/__tests__/render-scene-skin-lifecycle.integration.test.ts +173 -0
  409. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +133 -0
  410. package/src/__tests__/render-target-material-source.test-d.ts +27 -3
  411. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +61 -1
  412. package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
  413. package/src/__tests__/shader-manifest-fixture.ts +39 -0
  414. package/src/__tests__/skin-motion-regression.unit.test.ts +0 -33
  415. package/src/__tests__/skin-palette-persistent.integration.test.ts +28 -0
  416. package/src/__tests__/skin-palette-persistent.unit.test.ts +247 -0
  417. package/src/__tests__/skinned-shadow-caster.test.ts +118 -14
  418. package/src/__tests__/specular-environment-scale.dawn.test.ts +156 -0
  419. package/src/__tests__/ssr-admission-matrix.integration.test.ts +7 -1
  420. package/src/__tests__/ssr-confidence-compose.unit.test.ts +84 -0
  421. package/src/__tests__/ssr-coordinate-oracle.unit.test.ts +28 -0
  422. package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
  423. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +91 -0
  424. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +112 -0
  425. package/src/__tests__/ssr-gpu-dispatch.ts +946 -0
  426. package/src/__tests__/ssr-graph-topology.unit.test.ts +104 -0
  427. package/src/__tests__/ssr-history-filter.dawn.test.ts +198 -0
  428. package/src/__tests__/ssr-hit-color.dawn.test.ts +273 -0
  429. package/src/__tests__/ssr-hiz-odd-reduction.dawn.test.ts +569 -0
  430. package/src/__tests__/ssr-hiz-rescue.dawn.test.ts +279 -0
  431. package/src/__tests__/ssr-hiz.browser.test.ts +150 -0
  432. package/src/__tests__/ssr-hiz.dawn.test.ts +150 -0
  433. package/src/__tests__/ssr-hiz.unit.test.ts +56 -0
  434. package/src/__tests__/ssr-inspection.unit.test.ts +105 -0
  435. package/src/__tests__/ssr-memory-budget.unit.test.ts +45 -0
  436. package/src/__tests__/ssr-performance-sequence-aggregation.unit.test.ts +15 -0
  437. package/src/__tests__/ssr-public-surface.test-d.ts +37 -0
  438. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +387 -0
  439. package/src/__tests__/ssr-reflection-mip-reducer.dawn.test.ts +309 -0
  440. package/src/__tests__/ssr-reprojection-probe.ts +90 -0
  441. package/src/__tests__/ssr-roughness-mip.dawn.test.ts +163 -0
  442. package/src/__tests__/ssr-shader-prewarm.unit.test.ts +59 -0
  443. package/src/__tests__/ssr-spatial.integration.test.ts +141 -0
  444. package/src/__tests__/ssr-stable-lattice.dawn.test.ts +475 -0
  445. package/src/__tests__/ssr-temporal-history.unit.test.ts +202 -0
  446. package/src/__tests__/ssr-texel-crossing.dawn.test.ts +448 -0
  447. package/src/__tests__/ssr-zero-work.integration.test.ts +87 -0
  448. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +44 -12
  449. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +29 -0
  450. package/src/__tests__/standard-output-chain-contract.unit.test.ts +99 -0
  451. package/src/__tests__/standard-output-chain.integration.test.ts +73 -0
  452. package/src/__tests__/standard-output-gpu-evidence.ts +205 -0
  453. package/src/__tests__/standard-output.browser.test.ts +15 -0
  454. package/src/__tests__/standard-output.dawn.test.ts +15 -0
  455. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +38 -0
  456. package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
  457. package/src/__tests__/standard-profile-oracle.unit.test.ts +22 -0
  458. package/src/__tests__/standard-surface-lighting.unit.test.ts +41 -0
  459. package/src/__tests__/standard-texture-specialization.dawn.test.ts +141 -0
  460. package/src/__tests__/surface-adjacent-regressions.integration.test.ts +6 -3
  461. package/src/__tests__/taa-coverage-edge.dawn.test.ts +193 -0
  462. package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
  463. package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +778 -0
  464. package/src/__tests__/taa-stability-feedback.browser.test.ts +23 -0
  465. package/src/__tests__/taa-stability-feedback.dawn.test.ts +68 -0
  466. package/src/__tests__/taa-stability-feedback.ts +341 -0
  467. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +49 -7
  468. package/src/__tests__/temporal-reset-matrix.unit.test.ts +9 -0
  469. package/src/__tests__/temporal-transaction.integration.test.ts +28 -0
  470. package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
  471. package/src/__tests__/typed-pipeline-topology.unit.test.ts +109 -4
  472. package/src/__tests__/typed-scene-pass-material-cache.integration.test.ts +126 -0
  473. package/src/__tests__/vertex-layouts-ssot.unit.test.ts +47 -0
  474. package/src/__tests__/visibility-extract.perf.test.ts +20 -8
  475. package/src/__tests__/visibility-instances.integration.test.ts +19 -7
  476. package/src/__tests__/visibility-producer-matrix.integration.test.ts +20 -9
  477. package/src/assembly/atmosphere-shader-prewarm.ts +38 -0
  478. package/src/assembly/dynamic-geometry-host.ts +887 -0
  479. package/src/assembly/dynamic-geometry-runtime.ts +71 -0
  480. package/src/assembly/factory.ts +4 -0
  481. package/src/assembly/gpu-driven-owner.ts +29 -0
  482. package/src/assembly/host-contract.ts +36 -0
  483. package/src/assembly/material/assembly.ts +38 -0
  484. package/src/assembly/material-shader-policy.ts +71 -28
  485. package/src/assembly/recovery/failure-location.ts +62 -0
  486. package/src/assembly/recovery/renderer-recover.ts +19 -17
  487. package/src/assembly/renderer-facade.ts +29 -0
  488. package/src/assembly/renderer-feature-inspection.ts +13 -0
  489. package/src/assembly/renderer-frame-transaction.ts +63 -0
  490. package/src/assembly/renderer-helpers.ts +26 -0
  491. package/src/assembly/renderer-inspection.ts +6 -0
  492. package/src/assembly/shader-prewarm-policy.ts +32 -0
  493. package/src/assembly/skin-palette-owner.ts +21 -0
  494. package/src/assembly/ssr-shader-prewarm.ts +41 -0
  495. package/src/assembly/webgpu-device-loss.ts +75 -0
  496. package/src/assembly/webgpu-pbr-ready.ts +232 -0
  497. package/src/assembly/webgpu-ready-mipmap.ts +26 -0
  498. package/src/assembly/webgpu-ready.ts +142 -121
  499. package/src/assembly/webgpu-renderer-bootstrap.ts +85 -0
  500. package/src/assembly/webgpu-renderer-contract.ts +69 -0
  501. package/src/assembly/webgpu-renderer-guards.ts +32 -0
  502. package/src/assembly/webgpu-renderer-observation.ts +43 -0
  503. package/src/assembly/webgpu-renderer-recovery-failure.ts +62 -0
  504. package/src/assembly/webgpu-renderer.ts +675 -614
  505. package/src/assembly/webgpu-vertex-layouts.ts +233 -87
  506. package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
  507. package/src/components/camera.ts +287 -7
  508. package/src/components/index.ts +1 -0
  509. package/src/components/instances.ts +45 -18
  510. package/src/components/scene-instance.ts +2 -1
  511. package/src/components/screen-space-reflection.ts +21 -0
  512. package/src/components/sprite-animation.ts +3 -3
  513. package/src/components/sprite-instances.ts +1 -1
  514. package/src/device/gpu-residency.ts +96 -93
  515. package/src/device/mesh-residency-lifetime.ts +73 -0
  516. package/src/dynamic-geometry.ts +736 -0
  517. package/src/environment/background.ts +263 -0
  518. package/src/errors/gpu-driven.ts +39 -5
  519. package/src/errors/render.ts +27 -3
  520. package/src/extract/camera.ts +26 -1
  521. package/src/extract/gpu-driven.ts +185 -10
  522. package/src/features/host.ts +237 -19
  523. package/src/features/noise-texture.ts +91 -0
  524. package/src/features/plan.ts +553 -24
  525. package/src/features/prepared-gpu-work.ts +631 -49
  526. package/src/features/prepared-graphics-store.ts +31 -0
  527. package/src/features/prepared-graphics.ts +5 -0
  528. package/src/features/render-graph-compute.ts +41 -8
  529. package/src/features/render-graph-contribution.ts +141 -3
  530. package/src/features/render-graph-raster.ts +143 -30
  531. package/src/features/types.ts +11 -0
  532. package/src/fullscreen-post-process-pass.ts +3 -0
  533. package/src/gpu-driven/batch-topology.ts +424 -102
  534. package/src/gpu-driven/pbr-program.ts +31 -0
  535. package/src/gpu-driven/prepared-draw.ts +29 -4
  536. package/src/gpu-driven/production-raster.ts +2267 -694
  537. package/src/gpu-driven/shadow-views.ts +539 -0
  538. package/src/gpu-driven/view-gpu.ts +188 -41
  539. package/src/gpu-scene-schema.ts +52 -11
  540. package/src/gpu-scene.ts +186 -99
  541. package/src/gpu-texture-usage.ts +1 -0
  542. package/src/hdrp-buffers.ts +72 -36
  543. package/src/ibl/frame-resources.ts +38 -0
  544. package/src/ibl/skylight-bind-group.ts +5 -4
  545. package/src/index.ts +125 -1
  546. package/src/inspection-types.ts +191 -0
  547. package/src/instances-derived-bounds.ts +258 -34
  548. package/src/instances.ts +459 -150
  549. package/src/internal.ts +22 -0
  550. package/src/lifecycle.ts +2 -0
  551. package/src/material-row.ts +145 -0
  552. package/src/materials.ts +44 -8
  553. package/src/pbr-pipeline.ts +159 -17
  554. package/src/pipeline/standard-forward-lane.ts +52 -24
  555. package/src/pipeline/standard-output/__tests__/lut-admission.unit.test.ts +103 -0
  556. package/src/pipeline/standard-output/auto-exposure/__tests__/capability.unit.test.ts +40 -0
  557. package/src/pipeline/standard-output/auto-exposure/__tests__/gpu.contract.unit.test.ts +125 -0
  558. package/src/pipeline/standard-output/auto-exposure/__tests__/graph.contract.unit.test.ts +94 -0
  559. package/src/pipeline/standard-output/auto-exposure/__tests__/oracle.test.ts +108 -0
  560. package/src/pipeline/standard-output/auto-exposure/__tests__/preset.test.ts +26 -0
  561. package/src/pipeline/standard-output/auto-exposure/capability.ts +38 -0
  562. package/src/pipeline/standard-output/auto-exposure/gpu.ts +567 -0
  563. package/src/pipeline/standard-output/auto-exposure/graph.ts +221 -0
  564. package/src/pipeline/standard-output/auto-exposure/inspection.ts +231 -0
  565. package/src/pipeline/standard-output/auto-exposure/oracle.ts +291 -0
  566. package/src/pipeline/standard-output/auto-exposure/preset.ts +28 -0
  567. package/src/pipeline/standard-output/auto-exposure/state.ts +156 -0
  568. package/src/pipeline/standard-output/color-transform.ts +124 -0
  569. package/src/pipeline/standard-output/graph.ts +139 -0
  570. package/src/pipeline/standard-output/lut-admission.ts +121 -0
  571. package/src/pipeline/standard-output/lut-gpu.ts +399 -0
  572. package/src/pipeline/standard-output/lut-state.ts +176 -0
  573. package/src/pipeline/standard-output/resources.ts +121 -0
  574. package/src/pipeline/standard-output/types.ts +58 -0
  575. package/src/pipeline/standard-pipeline.ts +192 -59
  576. package/src/pipeline/standard-post.ts +186 -27
  577. package/src/pipeline-builder.ts +16 -6
  578. package/src/pipeline-spec-types.ts +4 -0
  579. package/src/pipeline-spec.ts +37 -29
  580. package/src/points-lines/standard-owner.ts +6 -14
  581. package/src/prepare/prepared-graphics-resolver.ts +9 -2
  582. package/src/record/__tests__/material-slot-plan.unit.test.ts +48 -0
  583. package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
  584. package/src/record/__tests__/recovery-pipeline.unit.test.ts +2 -29
  585. package/src/record/__tests__/sprite-material-abi.unit.test.ts +36 -5
  586. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +45 -0
  587. package/src/record/__tests__/view-ubo-layout.unit.test.ts +5 -0
  588. package/src/record/dynamic-geometry-consumption.ts +59 -0
  589. package/src/record/frame-lighting.ts +12 -11
  590. package/src/record/frame-snapshot.ts +133 -23
  591. package/src/record/frame-targets.ts +9 -0
  592. package/src/record/frame.ts +727 -133
  593. package/src/record/main-pass-geometry.ts +162 -98
  594. package/src/record/main-pass-material.ts +115 -26
  595. package/src/record/main-pass-sprite-draws.ts +18 -107
  596. package/src/record/main-pass.ts +78 -8
  597. package/src/record/material-uniforms.ts +1 -1
  598. package/src/record/mesh-ssbo.ts +59 -15
  599. package/src/record/prepared-material-bindings.ts +234 -0
  600. package/src/record/recovery-pipeline.ts +59 -136
  601. package/src/record/render-context.ts +92 -22
  602. package/src/record/shadow-pass.ts +1231 -209
  603. package/src/record/skybox-post-pass.ts +14 -3
  604. package/src/record/typed-frame-graph.ts +1006 -53
  605. package/src/record/view-ubo.ts +11 -0
  606. package/src/recovery/render-system-candidate.ts +90 -66
  607. package/src/recovery/render-system-roots.ts +113 -0
  608. package/src/recovery/types.ts +77 -0
  609. package/src/reflection/record-owner.ts +26 -54
  610. package/src/render-contract.ts +219 -25
  611. package/src/render-graph-primitives.ts +6 -2
  612. package/src/render-pipeline.ts +70 -1
  613. package/src/render-system-extract-tail.ts +409 -160
  614. package/src/render-system-extract.ts +376 -102
  615. package/src/render-system-projections.ts +241 -0
  616. package/src/render-system.ts +692 -791
  617. package/src/scene/render-scene-types.ts +13 -4
  618. package/src/scene/render-scene.ts +569 -355
  619. package/src/scene/shadow-visibility.ts +21 -0
  620. package/src/ssr/admission.ts +380 -14
  621. package/src/ssr/compose.ts +144 -0
  622. package/src/ssr/errors.ts +48 -0
  623. package/src/ssr/graph.ts +777 -0
  624. package/src/ssr/history.ts +436 -0
  625. package/src/ssr/hiz.ts +124 -0
  626. package/src/ssr/inspection.ts +124 -0
  627. package/src/ssr/resources.ts +202 -0
  628. package/src/ssr/temporal.ts +164 -0
  629. package/src/systems/skin-palette-allocator.ts +495 -148
  630. package/src/systems/skin-palette-types.ts +17 -0
  631. package/src/systems/transparent-dispatch.ts +90 -0
  632. package/src/targets/material-source.ts +34 -0
  633. package/src/temporal/coverage.ts +1 -1
  634. package/src/temporal/frame-coordinator.ts +23 -2
  635. package/src/temporal/gpu.ts +74 -12
  636. package/src/temporal/history.ts +3 -1
  637. package/src/temporal/inspection.ts +2 -1
  638. package/src/temporal/standard-scene-data.ts +3 -1
  639. package/src/temporal/temporal-view.ts +3 -0
  640. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +204 -139
  641. package/src/typed-render-graph-primitives.ts +266 -74
  642. package/src/typed-shadow-passes.ts +122 -12
  643. package/src/volume/temporal.ts +10 -0
  644. package/dist/chunk-ADHHVYLW.mjs.map +0 -1
  645. package/dist/chunk-FJ6P52EE.mjs.map +0 -1
  646. package/dist/chunk-GE3SDD72.mjs.map +0 -1
  647. package/dist/chunk-GF523LHF.mjs.map +0 -1
  648. package/dist/chunk-HKXTW355.mjs.map +0 -1
  649. package/dist/chunk-JDWARUOI.mjs.map +0 -1
  650. package/dist/chunk-KM2NOX2I.mjs.map +0 -1
  651. package/dist/chunk-TMIASV2N.mjs.map +0 -1
  652. package/dist/chunk-XDP6XE5V.mjs.map +0 -1
  653. package/dist/chunk-ZZ4YQ474.mjs.map +0 -1
  654. package/src/__tests__/instances-world-ownership.integration.test.ts +0 -62
  655. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +0 -36
@@ -0,0 +1,436 @@
1
+ import type {
2
+ Buffer,
3
+ RhiDevice,
4
+ RhiError,
5
+ RhiQueue,
6
+ Texture,
7
+ TextureDescriptor,
8
+ TextureView,
9
+ } from '@forgeax/engine-rhi';
10
+ import { err, ok, type Result } from '@forgeax/engine-types';
11
+ import type { DeviceScope } from '../device/device-scope';
12
+ import {
13
+ GPU_TEXTURE_USAGE_COPY_DST,
14
+ GPU_TEXTURE_USAGE_COPY_SRC,
15
+ GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
16
+ GPU_TEXTURE_USAGE_STORAGE_BINDING,
17
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING,
18
+ } from '../gpu-texture-usage';
19
+ import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from '../gpu-usage';
20
+
21
+ export const SSR_HISTORY_FORMAT = 'rgba16float' as const;
22
+ export type SsrHistoryResetReason =
23
+ | 'first-enable'
24
+ | 'resize'
25
+ | 'camera-cut'
26
+ | 'history-version'
27
+ | 'coverage-loss'
28
+ | 'reflection-generation'
29
+ | 'device-recovery'
30
+ | 'disable';
31
+ export type SsrHistoryFailureStage = 'build' | 'encode' | 'finish' | 'submit';
32
+ export type SsrHistoryState =
33
+ | 'first-frame'
34
+ | 'stable'
35
+ | 'reset'
36
+ | 'aborted'
37
+ | 'retiring'
38
+ | 'retired'
39
+ | 'disposed';
40
+
41
+ export interface SsrHistorySlot {
42
+ readonly texture: Texture;
43
+ readonly view: TextureView;
44
+ readonly surfaceTexture: Texture;
45
+ readonly surfaceView: TextureView;
46
+ }
47
+ export interface SsrHistoryResources {
48
+ readonly width: number;
49
+ readonly height: number;
50
+ readonly halfWidth: number;
51
+ readonly halfHeight: number;
52
+ readonly bytes: number;
53
+ readonly descriptor: TextureDescriptor;
54
+ readonly slots: readonly [SsrHistorySlot, SsrHistorySlot];
55
+ /** One renderer-owned parameter block shared by the temporal resolve. */
56
+ readonly paramsBuffer: Buffer;
57
+ readonly childScope: DeviceScope;
58
+ }
59
+ export interface SsrHistoryCandidate {
60
+ readonly readSlot: 0 | 1 | null;
61
+ readonly writeSlot: 0 | 1;
62
+ readonly historyValid: boolean;
63
+ }
64
+ export interface SsrHistoryInspection {
65
+ readonly state: SsrHistoryState;
66
+ readonly width: number;
67
+ readonly height: number;
68
+ readonly halfWidth: number;
69
+ readonly halfHeight: number;
70
+ readonly format: typeof SSR_HISTORY_FORMAT;
71
+ readonly historyCount: 0 | 2;
72
+ readonly historyValid: boolean;
73
+ readonly readSlot: 0 | 1 | null;
74
+ readonly writeSlot: 0 | 1;
75
+ readonly activeBytes: number;
76
+ readonly candidateBytes: number;
77
+ readonly retiringBytes: number;
78
+ readonly resetCount: number;
79
+ readonly resetReason: SsrHistoryResetReason | undefined;
80
+ readonly lastFailure: SsrHistoryFailureStage | undefined;
81
+ }
82
+ export interface SsrHistoryError {
83
+ readonly code:
84
+ | 'ssr-history-unavailable'
85
+ | 'ssr-history-active'
86
+ | 'ssr-history-not-active'
87
+ | 'ssr-history-retired';
88
+ readonly expected: string;
89
+ readonly hint: string;
90
+ readonly detail?: Readonly<{
91
+ readonly stage?: SsrHistoryFailureStage;
92
+ readonly reason?: SsrHistoryResetReason;
93
+ }>;
94
+ }
95
+
96
+ const HISTORY_USAGE =
97
+ GPU_TEXTURE_USAGE_COPY_SRC |
98
+ GPU_TEXTURE_USAGE_COPY_DST |
99
+ GPU_TEXTURE_USAGE_TEXTURE_BINDING |
100
+ GPU_TEXTURE_USAGE_STORAGE_BINDING |
101
+ GPU_TEXTURE_USAGE_RENDER_ATTACHMENT;
102
+
103
+ function positiveDimension(value: number, field: string): number {
104
+ if (!Number.isSafeInteger(value) || value <= 0) {
105
+ throw new RangeError(`${field} must be a positive safe integer.`);
106
+ }
107
+ return value;
108
+ }
109
+
110
+ function createResources(
111
+ device: RhiDevice,
112
+ scope: DeviceScope,
113
+ width: number,
114
+ height: number,
115
+ ): Result<SsrHistoryResources, RhiError> {
116
+ const halfWidth = Math.max(1, Math.floor(width / 2));
117
+ const halfHeight = Math.max(1, Math.floor(height / 2));
118
+ const descriptor: TextureDescriptor = {
119
+ label: 'ssr-history-rgba16float',
120
+ size: { width: halfWidth, height: halfHeight, depthOrArrayLayers: 1 },
121
+ format: SSR_HISTORY_FORMAT,
122
+ usage: HISTORY_USAGE,
123
+ mipLevelCount: 1,
124
+ sampleCount: 1,
125
+ dimension: '2d',
126
+ viewFormats: undefined,
127
+ textureBindingViewDimension: undefined,
128
+ };
129
+ const childScope = scope.createChild(`${scope.owner}:ssr-history`);
130
+ const slots: SsrHistorySlot[] = [];
131
+ for (const index of [0, 1] as const) {
132
+ const texture = device.createTexture({
133
+ ...descriptor,
134
+ label: `ssr-history-rgba16float-${index}`,
135
+ });
136
+ if (!texture.ok) {
137
+ childScope.abandon();
138
+ return texture;
139
+ }
140
+ childScope._adopt('texture', texture.value, (value) => {
141
+ device.destroyTexture(value);
142
+ });
143
+ const view = device.createTextureView(texture.value, {
144
+ label: `ssr-history-rgba16float-${index}.view`,
145
+ dimension: '2d',
146
+ baseMipLevel: 0,
147
+ mipLevelCount: 1,
148
+ baseArrayLayer: 0,
149
+ arrayLayerCount: 1,
150
+ });
151
+ if (!view.ok) {
152
+ childScope.abandon();
153
+ return view;
154
+ }
155
+ const surfaceTexture = device.createTexture({
156
+ ...descriptor,
157
+ label: `ssr-history-surface-${index}`,
158
+ format: 'rgba8unorm',
159
+ });
160
+ if (!surfaceTexture.ok) {
161
+ childScope.abandon();
162
+ return surfaceTexture;
163
+ }
164
+ childScope._adopt('texture', surfaceTexture.value, (value) => {
165
+ device.destroyTexture(value);
166
+ });
167
+ const surfaceView = device.createTextureView(surfaceTexture.value, { dimension: '2d' });
168
+ if (!surfaceView.ok) {
169
+ childScope.abandon();
170
+ return surfaceView;
171
+ }
172
+ slots.push({
173
+ texture: texture.value,
174
+ view: view.value,
175
+ surfaceTexture: surfaceTexture.value,
176
+ surfaceView: surfaceView.value,
177
+ });
178
+ }
179
+ const params = device.createBuffer({
180
+ label: 'ssr-temporal-params',
181
+ size: 32,
182
+ usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
183
+ mappedAtCreation: false,
184
+ });
185
+ if (!params.ok) {
186
+ childScope.abandon();
187
+ return params;
188
+ }
189
+ childScope._adopt('buffer', params.value, (value) => {
190
+ device.destroyBuffer(value);
191
+ });
192
+ const cleared = device.queue.writeBuffer(params.value, 0, new Uint8Array(32));
193
+ if (!cleared.ok) {
194
+ childScope.abandon();
195
+ return cleared;
196
+ }
197
+ return ok({
198
+ width,
199
+ height,
200
+ halfWidth,
201
+ halfHeight,
202
+ bytes: halfWidth * halfHeight * 12 * 2,
203
+ descriptor,
204
+ slots: slots as [SsrHistorySlot, SsrHistorySlot],
205
+ paramsBuffer: params.value,
206
+ childScope,
207
+ });
208
+ }
209
+
210
+ function failure(
211
+ code: SsrHistoryError['code'],
212
+ expected: string,
213
+ hint: string,
214
+ detail?: SsrHistoryError['detail'],
215
+ ): SsrHistoryError {
216
+ return { code, expected, hint, ...(detail === undefined ? {} : { detail }) };
217
+ }
218
+
219
+ /** Owns only SSR's two physical history slots; the shared coordinator owns epochs. */
220
+ export class SsrHistoryOwner {
221
+ private activeResources: SsrHistoryResources | undefined;
222
+ private readonly retiringResources = new Set<SsrHistoryResources>();
223
+ private retirementFencePending = false;
224
+ private activeCandidate: SsrHistoryCandidate | undefined;
225
+ private readIndex: 0 | 1 = 0;
226
+ private valid = false;
227
+ private state: SsrHistoryState = 'first-frame';
228
+ private resetReason: SsrHistoryResetReason | undefined = 'first-enable';
229
+ private lastFailure: SsrHistoryFailureStage | undefined;
230
+ private resetCount = 0;
231
+
232
+ private constructor(
233
+ private readonly device: RhiDevice,
234
+ private readonly scope: DeviceScope,
235
+ resources: SsrHistoryResources,
236
+ ) {
237
+ this.activeResources = resources;
238
+ }
239
+
240
+ static create(input: {
241
+ readonly device: RhiDevice;
242
+ readonly scope: DeviceScope;
243
+ readonly width: number;
244
+ readonly height: number;
245
+ }): Result<SsrHistoryOwner, RhiError> {
246
+ const width = positiveDimension(input.width, 'width');
247
+ const height = positiveDimension(input.height, 'height');
248
+ const resources = createResources(input.device, input.scope, width, height);
249
+ return resources.ok
250
+ ? ok(new SsrHistoryOwner(input.device, input.scope, resources.value))
251
+ : resources;
252
+ }
253
+
254
+ get resources(): SsrHistoryResources {
255
+ if (this.activeResources === undefined) throw new Error('SSR history resources are retired.');
256
+ return this.activeResources;
257
+ }
258
+
259
+ beginFrame(): Result<SsrHistoryCandidate, SsrHistoryError> {
260
+ if (
261
+ this.activeResources === undefined ||
262
+ this.state === 'retired' ||
263
+ this.state === 'disposed'
264
+ ) {
265
+ return err(
266
+ failure(
267
+ 'ssr-history-retired',
268
+ 'SSR history resources are active',
269
+ 'recreate the renderer-owned SSR history after device recovery',
270
+ ),
271
+ );
272
+ }
273
+ if (this.activeCandidate !== undefined) {
274
+ return err(
275
+ failure(
276
+ 'ssr-history-active',
277
+ 'one SSR history candidate is active',
278
+ 'commit or abort the active SSR history candidate before beginning another',
279
+ ),
280
+ );
281
+ }
282
+ const writeSlot: 0 | 1 = this.valid ? (this.readIndex === 0 ? 1 : 0) : 0;
283
+ const candidate = Object.freeze({
284
+ readSlot: this.valid ? this.readIndex : null,
285
+ writeSlot,
286
+ historyValid: this.valid && this.resetReason === undefined,
287
+ }) as SsrHistoryCandidate;
288
+ this.activeCandidate = candidate;
289
+ this.state = this.valid ? 'stable' : this.state === 'aborted' ? 'aborted' : 'first-frame';
290
+ this.lastFailure = undefined;
291
+ return ok(candidate);
292
+ }
293
+
294
+ commitFrame(candidate: SsrHistoryCandidate): Result<void, SsrHistoryError> {
295
+ if (this.activeCandidate !== candidate) {
296
+ return err(
297
+ failure(
298
+ 'ssr-history-not-active',
299
+ 'commit the candidate returned by beginFrame',
300
+ 'keep one candidate from beginFrame until the shared queue submit succeeds',
301
+ ),
302
+ );
303
+ }
304
+ this.readIndex = candidate.writeSlot;
305
+ this.valid = true;
306
+ this.activeCandidate = undefined;
307
+ this.state = 'stable';
308
+ this.resetReason = undefined;
309
+ this.lastFailure = undefined;
310
+ return ok(undefined);
311
+ }
312
+
313
+ abortFrame(candidate: SsrHistoryCandidate, stage: SsrHistoryFailureStage): void {
314
+ if (this.activeCandidate !== candidate) return;
315
+ this.activeCandidate = undefined;
316
+ this.state = 'aborted';
317
+ this.lastFailure = stage;
318
+ }
319
+
320
+ reset(reason: SsrHistoryResetReason): void {
321
+ this.activeCandidate = undefined;
322
+ this.valid = false;
323
+ this.readIndex = 0;
324
+ this.resetReason = reason;
325
+ this.lastFailure = undefined;
326
+ this.resetCount += 1;
327
+ if (this.activeResources !== undefined) this.state = 'reset';
328
+ }
329
+
330
+ resize(width: number, height: number): Result<void, RhiError> {
331
+ const next = createResources(
332
+ this.device,
333
+ this.scope,
334
+ positiveDimension(width, 'width'),
335
+ positiveDimension(height, 'height'),
336
+ );
337
+ if (!next.ok) return next;
338
+ if (this.activeResources !== undefined) this.retiringResources.add(this.activeResources);
339
+ this.activeResources = next.value;
340
+ this.activeCandidate = undefined;
341
+ this.valid = false;
342
+ this.readIndex = 0;
343
+ this.resetReason = 'resize';
344
+ this.lastFailure = undefined;
345
+ this.resetCount += 1;
346
+ this.state = 'reset';
347
+ return ok(undefined);
348
+ }
349
+
350
+ /** Retire pending allocations after the queue's already-submitted work. */
351
+ retireAfterFence(queue: RhiQueue, onFailure: (cause: unknown) => void): void {
352
+ if (this.retirementFencePending) return;
353
+ if (this.retiringResources.size === 0 && this.activeResources !== undefined) {
354
+ this.retiringResources.add(this.activeResources);
355
+ this.activeCandidate = undefined;
356
+ this.valid = false;
357
+ this.state = 'retiring';
358
+ }
359
+ const pending = [...this.retiringResources];
360
+ for (const resources of pending) resources.childScope.beginRetire();
361
+ if (pending.length === 0) return;
362
+ this.retirementFencePending = true;
363
+ const finish = (): void => {
364
+ this.retirementFencePending = false;
365
+ for (const resources of pending) {
366
+ this.retiringResources.delete(resources);
367
+ resources.childScope.retire();
368
+ if (this.activeResources === resources) this.activeResources = undefined;
369
+ }
370
+ if (this.activeResources === undefined && this.retiringResources.size === 0) {
371
+ this.state = 'retired';
372
+ }
373
+ // A second resize may have added the then-active resources while this
374
+ // fence was pending. Chain another fence so every retired generation is
375
+ // eventually drained without making the record stage own a retirement
376
+ // ledger.
377
+ if (this.retiringResources.size > 0) this.retireAfterFence(queue, onFailure);
378
+ };
379
+ void queue.onSubmittedWorkDone().then(finish, (cause) => {
380
+ onFailure(cause);
381
+ finish();
382
+ });
383
+ }
384
+
385
+ retire(): void {
386
+ this.retirementFencePending = false;
387
+ this.activeCandidate = undefined;
388
+ if (this.activeResources !== undefined) {
389
+ this.activeResources.childScope.retire();
390
+ this.activeResources = undefined;
391
+ }
392
+ for (const resources of this.retiringResources) resources.childScope.retire();
393
+ this.retiringResources.clear();
394
+ this.valid = false;
395
+ this.state = 'retired';
396
+ }
397
+
398
+ dispose(): void {
399
+ if (this.state === 'disposed') return;
400
+ this.retire();
401
+ this.state = 'disposed';
402
+ }
403
+
404
+ inspect(): SsrHistoryInspection {
405
+ const active = this.activeResources;
406
+ return Object.freeze({
407
+ state: this.state,
408
+ width: active?.width ?? 0,
409
+ height: active?.height ?? 0,
410
+ halfWidth: active?.halfWidth ?? 0,
411
+ halfHeight: active?.halfHeight ?? 0,
412
+ format: SSR_HISTORY_FORMAT,
413
+ historyCount: active === undefined ? 0 : 2,
414
+ historyValid: this.valid,
415
+ readSlot: active === undefined ? null : this.valid ? this.readIndex : null,
416
+ writeSlot: active === undefined ? 0 : this.valid ? (this.readIndex === 0 ? 1 : 0) : 0,
417
+ activeBytes: active?.bytes ?? 0,
418
+ candidateBytes: 0,
419
+ retiringBytes: [...this.retiringResources]
420
+ .filter((entry) => entry !== active)
421
+ .reduce((sum, entry) => sum + entry.bytes, 0),
422
+ resetCount: this.resetCount,
423
+ resetReason: this.resetReason,
424
+ lastFailure: this.lastFailure,
425
+ });
426
+ }
427
+ }
428
+
429
+ export function createSsrHistoryOwner(input: {
430
+ readonly device: RhiDevice;
431
+ readonly scope: DeviceScope;
432
+ readonly width: number;
433
+ readonly height: number;
434
+ }): Result<SsrHistoryOwner, RhiError> {
435
+ return SsrHistoryOwner.create(input);
436
+ }
package/src/ssr/hiz.ts ADDED
@@ -0,0 +1,124 @@
1
+ import type { GraphExtent } from '@forgeax/engine-render-graph';
2
+
3
+ /** The one depth format owned by the SSR spatial producer. */
4
+ export const SSR_HIZ_FORMAT = 'r32float' as const;
5
+
6
+ export interface SsrHiZExtent {
7
+ readonly width: number;
8
+ readonly height: number;
9
+ }
10
+
11
+ export interface SsrHiZLevelPlan extends SsrHiZExtent {
12
+ readonly level: number;
13
+ }
14
+
15
+ export interface SsrHiZPlan {
16
+ readonly extent: SsrHiZExtent;
17
+ readonly format: typeof SSR_HIZ_FORMAT;
18
+ readonly mipLevelCount: number;
19
+ readonly levels: readonly SsrHiZLevelPlan[];
20
+ readonly graphSize: GraphExtent;
21
+ }
22
+
23
+ function validExtent(extent: SsrHiZExtent): boolean {
24
+ return (
25
+ Number.isInteger(extent.width) &&
26
+ Number.isInteger(extent.height) &&
27
+ extent.width > 0 &&
28
+ extent.height > 0
29
+ );
30
+ }
31
+
32
+ function requireExtent(extent: SsrHiZExtent): void {
33
+ if (!validExtent(extent)) {
34
+ throw new RangeError('SSR Hi-Z extent must contain positive integer width and height');
35
+ }
36
+ }
37
+
38
+ /** Derive the physical WebGPU floor-halved mip extent, clamped to one texel. */
39
+ export function nextSsrHiZMipExtent(extent: SsrHiZExtent): SsrHiZExtent {
40
+ requireExtent(extent);
41
+ return {
42
+ width: Math.max(1, Math.floor(extent.width / 2)),
43
+ height: Math.max(1, Math.floor(extent.height / 2)),
44
+ };
45
+ }
46
+
47
+ /** Derive the complete current-view Hi-Z descriptor without allocating a resource. */
48
+ export function buildSsrHiZPlan(extent: SsrHiZExtent): SsrHiZPlan {
49
+ requireExtent(extent);
50
+ const levels: SsrHiZLevelPlan[] = [];
51
+ let current = { width: extent.width, height: extent.height };
52
+ let level = 0;
53
+ while (true) {
54
+ levels.push({ level, ...current });
55
+ if (current.width === 1 && current.height === 1) break;
56
+ current = nextSsrHiZMipExtent(current);
57
+ level += 1;
58
+ }
59
+ return Object.freeze({
60
+ extent: Object.freeze({ width: extent.width, height: extent.height }),
61
+ format: SSR_HIZ_FORMAT,
62
+ mipLevelCount: levels.length,
63
+ levels: Object.freeze(levels.map((entry) => Object.freeze(entry))),
64
+ graphSize: Object.freeze({ width: extent.width, height: extent.height }),
65
+ });
66
+ }
67
+
68
+ /** Map an invalid or empty depth sample to the Hi-Z empty-pixel sentinel. */
69
+ export function normalizeSsrHiZDepth(value: number): number {
70
+ return Number.isFinite(value) && value > 0 ? value : Number.POSITIVE_INFINITY;
71
+ }
72
+
73
+ function ssrHiZCoverageStart(index: number, sourceSize: number, destinationSize: number): number {
74
+ return Math.floor((index * sourceSize) / destinationSize);
75
+ }
76
+
77
+ function ssrHiZCoverageEnd(index: number, sourceSize: number, destinationSize: number): number {
78
+ return Math.min(
79
+ sourceSize,
80
+ Math.floor(((index + 1) * sourceSize + destinationSize - 1) / destinationSize),
81
+ );
82
+ }
83
+
84
+ /**
85
+ * Reduce one mip level with the physical mip's complete coverage footprint.
86
+ *
87
+ * WebGPU mip dimensions are floor-halved, so a 3-wide source has a 1-wide
88
+ * destination. The destination cells therefore use integer normalized
89
+ * boundaries with a conservative ceil on the end boundary instead of
90
+ * assuming a fixed 2x2 footprint. Adjacent cells overlap at odd boundaries;
91
+ * this keeps boundary and trailing source columns/rows in the hierarchy.
92
+ * The empty sentinel is infinity and therefore never wins over a finite
93
+ * positive view-space depth. Invalid input samples are treated as empty so a
94
+ * malformed depth cannot introduce NaN into the hierarchy.
95
+ */
96
+ export function reduceSsrHiZLevel(
97
+ source: ArrayLike<number>,
98
+ sourceExtent: SsrHiZExtent,
99
+ ): Float32Array {
100
+ requireExtent(sourceExtent);
101
+ const expectedLength = sourceExtent.width * sourceExtent.height;
102
+ if (source.length !== expectedLength) {
103
+ throw new RangeError(`SSR Hi-Z source length must equal ${expectedLength}`);
104
+ }
105
+ const destination = nextSsrHiZMipExtent(sourceExtent);
106
+ const reduced = new Float32Array(destination.width * destination.height);
107
+ for (let y = 0; y < destination.height; y += 1) {
108
+ for (let x = 0; x < destination.width; x += 1) {
109
+ let minimum = Number.POSITIVE_INFINITY;
110
+ const startY = ssrHiZCoverageStart(y, sourceExtent.height, destination.height);
111
+ const endY = ssrHiZCoverageEnd(y, sourceExtent.height, destination.height);
112
+ const startX = ssrHiZCoverageStart(x, sourceExtent.width, destination.width);
113
+ const endX = ssrHiZCoverageEnd(x, sourceExtent.width, destination.width);
114
+ for (let sampleY = startY; sampleY < endY; sampleY += 1) {
115
+ for (let sampleX = startX; sampleX < endX; sampleX += 1) {
116
+ const sample = normalizeSsrHiZDepth(source[sampleY * sourceExtent.width + sampleX] ?? 0);
117
+ minimum = Math.min(minimum, sample);
118
+ }
119
+ }
120
+ reduced[y * destination.width + x] = minimum;
121
+ }
122
+ }
123
+ return reduced;
124
+ }
@@ -0,0 +1,124 @@
1
+ // @forgeax/engine-render - bounded SSR spatial inspection projection.
2
+
3
+ import type { ScreenSpaceReflectionData } from '../components/screen-space-reflection';
4
+ import type { ReflectionFallbackSource } from '../inspection-types';
5
+ import type { SsrSpatialAdmission, SsrSpatialLane, SsrSpatialWork } from './admission';
6
+ import type { SsrConfigInvalidError, SsrUnavailableError } from './errors';
7
+ import type { SsrHistoryState } from './history';
8
+
9
+ export type SsrSpatialInspectionFailure = SsrConfigInvalidError | SsrUnavailableError;
10
+
11
+ export interface SsrSpatialHistoryInspection {
12
+ readonly state: 'not-owned' | SsrHistoryState;
13
+ readonly bytes: number;
14
+ readonly resetCount: number;
15
+ }
16
+
17
+ export interface SsrSpatialInspectionProjection {
18
+ readonly status?: SsrSpatialInspection['status'];
19
+ readonly coverage?: Partial<SsrSpatialInspection['coverage']>;
20
+ readonly history?: SsrSpatialHistoryInspection;
21
+ readonly passRoster?: readonly string[];
22
+ readonly fallbackSource?: ReflectionFallbackSource;
23
+ readonly failure?: SsrSpatialInspectionFailure;
24
+ }
25
+
26
+ /** Keep the public projection bounded even if a graph owner supplies a bad list. */
27
+ export const SSR_INSPECTION_MAX_PASSES = 64 as const;
28
+
29
+ function nonNegativeSafeInteger(name: string, value: number): number {
30
+ if (!Number.isSafeInteger(value) || value < 0) {
31
+ throw new Error(`${name} must be a non-negative safe integer`);
32
+ }
33
+ return value;
34
+ }
35
+
36
+ function copyHistory(history: SsrSpatialHistoryInspection): SsrSpatialHistoryInspection {
37
+ nonNegativeSafeInteger('SSR inspection history.bytes', history.bytes);
38
+ nonNegativeSafeInteger('SSR inspection history.resetCount', history.resetCount);
39
+ return Object.freeze({
40
+ state: history.state,
41
+ bytes: history.bytes,
42
+ resetCount: history.resetCount,
43
+ });
44
+ }
45
+
46
+ function copyCoverage(
47
+ coverage: Partial<SsrSpatialInspection['coverage']> | undefined,
48
+ ): SsrSpatialInspection['coverage'] {
49
+ const result = {
50
+ hitCount: coverage?.hitCount ?? null,
51
+ fallbackCount: coverage?.fallbackCount ?? null,
52
+ excludedCount: coverage?.excludedCount ?? null,
53
+ };
54
+ for (const [key, value] of Object.entries(result)) {
55
+ if (value !== null) nonNegativeSafeInteger(`SSR inspection coverage.${key}`, value);
56
+ }
57
+ return Object.freeze(result);
58
+ }
59
+
60
+ function copyPassRoster(passRoster: readonly string[] | undefined): readonly string[] {
61
+ return Object.freeze(
62
+ [...(passRoster ?? [])].slice(0, SSR_INSPECTION_MAX_PASSES).map((name, index) => {
63
+ if (typeof name !== 'string' || name.length === 0) {
64
+ throw new Error(`SSR inspection passRoster[${index}] must be a non-empty string`);
65
+ }
66
+ return name;
67
+ }),
68
+ );
69
+ }
70
+
71
+ export interface SsrSpatialInspection {
72
+ readonly status: 'not-requested' | 'requested' | 'admitted' | 'fallback-only' | 'structural-only';
73
+ readonly lane: SsrSpatialLane;
74
+ readonly config: ScreenSpaceReflectionData | undefined;
75
+ readonly viewRange: number;
76
+ readonly coverage: {
77
+ /** Null means no GPU coverage measurement is available for this frame. */
78
+ readonly hitCount: number | null;
79
+ readonly fallbackCount: number | null;
80
+ readonly excludedCount: number | null;
81
+ };
82
+ readonly history: SsrSpatialHistoryInspection;
83
+ readonly work: SsrSpatialWork;
84
+ readonly passRoster: readonly string[];
85
+ readonly fallbackSource: ReflectionFallbackSource | undefined;
86
+ readonly failure: SsrSpatialInspectionFailure | undefined;
87
+ }
88
+
89
+ /** Project only detached, bounded facts from the spatial admission result. */
90
+ export function projectSsrSpatialInspection(
91
+ admission: SsrSpatialAdmission,
92
+ projection: SsrSpatialInspectionProjection = {},
93
+ ): SsrSpatialInspection {
94
+ const config = admission.config;
95
+ return Object.freeze({
96
+ status: projection.status ?? admission.status,
97
+ lane: admission.lane,
98
+ config:
99
+ config === undefined
100
+ ? undefined
101
+ : Object.freeze({
102
+ maxDistance: config.maxDistance,
103
+ thickness: config.thickness,
104
+ maxRoughness: config.maxRoughness,
105
+ }),
106
+ viewRange: admission.viewRange,
107
+ coverage: copyCoverage(projection.coverage),
108
+ history: copyHistory(
109
+ projection.history ?? {
110
+ state: 'not-owned' as const,
111
+ bytes: 0,
112
+ resetCount: 0,
113
+ },
114
+ ),
115
+ work: Object.freeze({ ...admission.work }),
116
+ passRoster: copyPassRoster(projection.passRoster),
117
+ fallbackSource: projection.fallbackSource,
118
+ failure: projection.failure ?? admission.failure,
119
+ });
120
+ }
121
+
122
+ export function serializeSsrSpatialInspection(inspection: SsrSpatialInspection): string {
123
+ return JSON.stringify(inspection);
124
+ }