@forgeax/engine-render 0.1.19 → 0.1.21

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 (452) hide show
  1. package/README.md +215 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/assembly/device-feature-admission.d.ts +18 -0
  4. package/dist/assembly/device-feature-admission.d.ts.map +1 -0
  5. package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
  6. package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
  7. package/dist/assembly/factory.d.ts +34 -20
  8. package/dist/assembly/factory.d.ts.map +1 -1
  9. package/dist/assembly/host-contract.d.ts +9 -0
  10. package/dist/assembly/host-contract.d.ts.map +1 -1
  11. package/dist/assembly/render-target-host.d.ts +46 -0
  12. package/dist/assembly/render-target-host.d.ts.map +1 -0
  13. package/dist/assets/render-asset-port.d.ts.map +1 -1
  14. package/dist/authoring.mjs +3 -0
  15. package/dist/authoring.mjs.map +1 -1
  16. package/dist/capture/cube-views.d.ts +21 -0
  17. package/dist/capture/cube-views.d.ts.map +1 -0
  18. package/dist/capture/scheduler.d.ts +54 -0
  19. package/dist/capture/scheduler.d.ts.map +1 -0
  20. package/dist/{chunk-RJRUS55L.mjs → chunk-5YADUCA7.mjs} +1896 -1624
  21. package/dist/chunk-5YADUCA7.mjs.map +1 -0
  22. package/dist/{chunk-LOSO4CTV.mjs → chunk-6OPXDQ2E.mjs} +423 -46
  23. package/dist/chunk-6OPXDQ2E.mjs.map +1 -0
  24. package/dist/{chunk-IPXCABEP.mjs → chunk-BXBQQKFQ.mjs} +3 -9
  25. package/dist/chunk-BXBQQKFQ.mjs.map +1 -0
  26. package/dist/chunk-FS2KNUQH.mjs +1294 -0
  27. package/dist/chunk-FS2KNUQH.mjs.map +1 -0
  28. package/dist/components/camera.d.ts +1 -0
  29. package/dist/components/camera.d.ts.map +1 -1
  30. package/dist/components/cube-camera.d.ts +20 -0
  31. package/dist/components/cube-camera.d.ts.map +1 -0
  32. package/dist/components/directional-light.d.ts +11 -2
  33. package/dist/components/directional-light.d.ts.map +1 -1
  34. package/dist/components/directional-shadow-filter.d.ts +25 -0
  35. package/dist/components/directional-shadow-filter.d.ts.map +1 -0
  36. package/dist/components/index.d.ts +2 -0
  37. package/dist/components/index.d.ts.map +1 -1
  38. package/dist/components/light-helpers.d.ts.map +1 -1
  39. package/dist/components/reflection-probe.d.ts +17 -0
  40. package/dist/components/reflection-probe.d.ts.map +1 -0
  41. package/dist/components/spot-light.d.ts +12 -0
  42. package/dist/components/spot-light.d.ts.map +1 -1
  43. package/dist/construct-renderer.mjs +8552 -1612
  44. package/dist/construct-renderer.mjs.map +1 -1
  45. package/dist/device/gpu-residency.d.ts +19 -2
  46. package/dist/device/gpu-residency.d.ts.map +1 -1
  47. package/dist/environment/frame.d.ts.map +1 -1
  48. package/dist/environment/lifecycle.d.ts +5 -0
  49. package/dist/environment/lifecycle.d.ts.map +1 -1
  50. package/dist/errors/render.d.ts +209 -93
  51. package/dist/errors/render.d.ts.map +1 -1
  52. package/dist/extract/directional-shadow-projection.d.ts +23 -0
  53. package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
  54. package/dist/extract/environment.d.ts +14 -0
  55. package/dist/extract/environment.d.ts.map +1 -1
  56. package/dist/extract/visibility.d.ts.map +1 -1
  57. package/dist/features/fullscreen.d.ts.map +1 -1
  58. package/dist/features/targets.d.ts.map +1 -1
  59. package/dist/features/types.d.ts +10 -0
  60. package/dist/features/types.d.ts.map +1 -1
  61. package/dist/fullscreen-post-process-pass.d.ts +13 -2
  62. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  63. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  64. package/dist/gpu-driven/production-raster.d.ts +0 -1
  65. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  66. package/dist/gpu-scene.d.ts.map +1 -1
  67. package/dist/gpu-usage.d.ts +2 -0
  68. package/dist/gpu-usage.d.ts.map +1 -1
  69. package/dist/hdrp-buffers.d.ts +19 -17
  70. package/dist/hdrp-buffers.d.ts.map +1 -1
  71. package/dist/ibl/IblPipelineCache.d.ts +4 -0
  72. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  73. package/dist/ibl/kernel-cache.d.ts +36 -0
  74. package/dist/ibl/kernel-cache.d.ts.map +1 -0
  75. package/dist/index.d.ts +35 -4
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.mjs +4 -4
  78. package/dist/index.mjs.map +1 -1
  79. package/dist/inspection-types.d.ts +51 -0
  80. package/dist/inspection-types.d.ts.map +1 -1
  81. package/dist/instances-derived-bounds.d.ts +50 -0
  82. package/dist/instances-derived-bounds.d.ts.map +1 -0
  83. package/dist/internal.mjs +1 -1
  84. package/dist/light-buffer-layout.d.ts +30 -13
  85. package/dist/light-buffer-layout.d.ts.map +1 -1
  86. package/dist/mesh-material-bindings.d.ts +54 -0
  87. package/dist/mesh-material-bindings.d.ts.map +1 -1
  88. package/dist/pbr-pipeline.d.ts +20 -7
  89. package/dist/pbr-pipeline.d.ts.map +1 -1
  90. package/dist/pipeline/standard-forward-lane.d.ts +2 -1
  91. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  92. package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
  93. package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
  94. package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
  95. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
  96. package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
  97. package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
  98. package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
  99. package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
  100. package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
  101. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
  102. package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
  103. package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
  104. package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
  105. package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
  106. package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
  107. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
  108. package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
  109. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
  110. package/dist/pipeline/standard-pipeline.d.ts +4 -13
  111. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  112. package/dist/pipeline/standard-post.d.ts.map +1 -1
  113. package/dist/pipeline/standard-profile.d.ts +12 -20
  114. package/dist/pipeline/standard-profile.d.ts.map +1 -1
  115. package/dist/pipeline-spec.d.ts +40 -7
  116. package/dist/pipeline-spec.d.ts.map +1 -1
  117. package/dist/point-shadow-inspection.d.ts +21 -0
  118. package/dist/point-shadow-inspection.d.ts.map +1 -0
  119. package/dist/record/frame-lighting.d.ts +29 -32
  120. package/dist/record/frame-lighting.d.ts.map +1 -1
  121. package/dist/record/frame-snapshot.d.ts +65 -15
  122. package/dist/record/frame-snapshot.d.ts.map +1 -1
  123. package/dist/record/frame-targets.d.ts +5 -0
  124. package/dist/record/frame-targets.d.ts.map +1 -1
  125. package/dist/record/frame.d.ts +12 -5
  126. package/dist/record/frame.d.ts.map +1 -1
  127. package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
  128. package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
  129. package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
  130. package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
  131. package/dist/record/gpu-pass-timing/index.d.ts +8 -0
  132. package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
  133. package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
  134. package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
  135. package/dist/record/gpu-pass-timing/session.d.ts +43 -0
  136. package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
  137. package/dist/record/gpu-timing.d.ts +37 -0
  138. package/dist/record/gpu-timing.d.ts.map +1 -0
  139. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  140. package/dist/record/main-pass-material.d.ts +23 -2
  141. package/dist/record/main-pass-material.d.ts.map +1 -1
  142. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  143. package/dist/record/main-pass.d.ts +2 -0
  144. package/dist/record/main-pass.d.ts.map +1 -1
  145. package/dist/record/render-context.d.ts +48 -3
  146. package/dist/record/render-context.d.ts.map +1 -1
  147. package/dist/record/shadow-pass.d.ts.map +1 -1
  148. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  149. package/dist/record/typed-frame-graph.d.ts +81 -5
  150. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  151. package/dist/record/view-ubo.d.ts +7 -4
  152. package/dist/record/view-ubo.d.ts.map +1 -1
  153. package/dist/reflection/filter.d.ts +22 -0
  154. package/dist/reflection/filter.d.ts.map +1 -0
  155. package/dist/reflection/gpu-table.d.ts +25 -0
  156. package/dist/reflection/gpu-table.d.ts.map +1 -0
  157. package/dist/reflection/projection.d.ts +91 -0
  158. package/dist/reflection/projection.d.ts.map +1 -0
  159. package/dist/render-contract.d.ts +114 -7
  160. package/dist/render-contract.d.ts.map +1 -1
  161. package/dist/render-data.d.ts +10 -6
  162. package/dist/render-data.d.ts.map +1 -1
  163. package/dist/render-graph-primitives.d.ts +1 -0
  164. package/dist/render-graph-primitives.d.ts.map +1 -1
  165. package/dist/render-pipeline.d.ts +78 -2
  166. package/dist/render-pipeline.d.ts.map +1 -1
  167. package/dist/render-system-extract.d.ts +113 -20
  168. package/dist/render-system-extract.d.ts.map +1 -1
  169. package/dist/render-system.d.ts +24 -3
  170. package/dist/render-system.d.ts.map +1 -1
  171. package/dist/renderer-inspect.d.ts +29 -0
  172. package/dist/renderer-inspect.d.ts.map +1 -0
  173. package/dist/renderer.d.ts +43 -0
  174. package/dist/renderer.d.ts.map +1 -0
  175. package/dist/scene/render-scene.d.ts +14 -0
  176. package/dist/scene/render-scene.d.ts.map +1 -1
  177. package/dist/shadow-atlas.d.ts +3 -3
  178. package/dist/shadow-atlas.d.ts.map +1 -1
  179. package/dist/ssao-buffers.d.ts +3 -0
  180. package/dist/ssao-buffers.d.ts.map +1 -1
  181. package/dist/targets/contracts.d.ts +66 -0
  182. package/dist/targets/contracts.d.ts.map +1 -0
  183. package/dist/targets/graph-projection.d.ts +29 -0
  184. package/dist/targets/graph-projection.d.ts.map +1 -0
  185. package/dist/targets/material-source.d.ts +34 -0
  186. package/dist/targets/material-source.d.ts.map +1 -0
  187. package/dist/targets/owner.d.ts +32 -0
  188. package/dist/targets/owner.d.ts.map +1 -0
  189. package/dist/targets/physical.d.ts +18 -0
  190. package/dist/targets/physical.d.ts.map +1 -0
  191. package/dist/targets/readback.d.ts +39 -0
  192. package/dist/targets/readback.d.ts.map +1 -0
  193. package/dist/temporal/frame.d.ts +44 -0
  194. package/dist/temporal/frame.d.ts.map +1 -0
  195. package/dist/temporal/index.mjs +3 -3
  196. package/dist/typed-render-graph-primitives.d.ts +6 -1
  197. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  198. package/dist/typed-shadow-atlas.d.ts +10 -0
  199. package/dist/typed-shadow-atlas.d.ts.map +1 -0
  200. package/dist/typed-shadow-passes.d.ts +1 -1
  201. package/dist/typed-shadow-passes.d.ts.map +1 -1
  202. package/dist/volume/capability.d.ts +57 -0
  203. package/dist/volume/capability.d.ts.map +1 -0
  204. package/dist/volume/component.d.ts +61 -0
  205. package/dist/volume/component.d.ts.map +1 -0
  206. package/dist/volume/extract.d.ts +11 -0
  207. package/dist/volume/extract.d.ts.map +1 -0
  208. package/dist/volume/inspection.d.ts +38 -0
  209. package/dist/volume/inspection.d.ts.map +1 -0
  210. package/dist/volume/passes.d.ts +38 -0
  211. package/dist/volume/passes.d.ts.map +1 -0
  212. package/dist/volume/recovery.d.ts +38 -0
  213. package/dist/volume/recovery.d.ts.map +1 -0
  214. package/dist/volume/resources.d.ts +57 -0
  215. package/dist/volume/resources.d.ts.map +1 -0
  216. package/dist/volume/temporal.d.ts +35 -0
  217. package/dist/volume/temporal.d.ts.map +1 -0
  218. package/package.json +20 -20
  219. package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
  220. package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
  221. package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
  222. package/src/__tests__/cluster-binner.unit.test.ts +35 -0
  223. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -2
  224. package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
  225. package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
  226. package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
  227. package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
  228. package/src/__tests__/cube-camera.integration.test.ts +42 -0
  229. package/src/__tests__/device-feature-admission.unit.test.ts +73 -0
  230. package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -3
  231. package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
  232. package/src/__tests__/factory-contract.integration.test.ts +255 -29
  233. package/src/__tests__/fog-component.unit.test.ts +67 -0
  234. package/src/__tests__/fog.integration.test.ts +86 -0
  235. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
  236. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -9
  237. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +17 -1
  238. package/src/__tests__/gpu-driven-production.integration.test.ts +16 -17
  239. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +12 -4
  240. package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
  241. package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
  242. package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
  243. package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
  244. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
  245. package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
  246. package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
  247. package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
  248. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
  249. package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
  250. package/src/__tests__/instances-culling.integration.test.ts +94 -0
  251. package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
  252. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -14
  253. package/src/__tests__/material-observation.integration.test.ts +101 -0
  254. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
  255. package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
  256. package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
  257. package/src/__tests__/public-surface.test-d.ts +10 -0
  258. package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
  259. package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
  260. package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
  261. package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
  262. package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
  263. package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
  264. package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
  265. package/src/__tests__/render-error-code-owner.test-d.ts +23 -3
  266. package/src/__tests__/render-feature-docs.unit.test.ts +1 -1
  267. package/src/__tests__/render-target-admission.unit.test.ts +80 -0
  268. package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
  269. package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
  270. package/src/__tests__/render-target-material-source.test-d.ts +30 -0
  271. package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
  272. package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
  273. package/src/__tests__/render-target-owner.unit.test.ts +122 -0
  274. package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
  275. package/src/__tests__/render-target-public-schema.json +107 -0
  276. package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
  277. package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
  278. package/src/__tests__/render-target-readback.integration.test.ts +90 -0
  279. package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
  280. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +76 -0
  281. package/src/__tests__/renderer-frame-transaction.integration.test.ts +1 -1
  282. package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
  283. package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
  284. package/src/__tests__/skin-motion-regression.unit.test.ts +132 -0
  285. package/src/__tests__/skinned-shadow-caster.test.ts +32 -2
  286. package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
  287. package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
  288. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +232 -0
  289. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +8 -5
  290. package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
  291. package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
  292. package/src/__tests__/standard-lighting-write.unit.test.ts +377 -0
  293. package/src/__tests__/standard-lighting.integration.test.ts +67 -0
  294. package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
  295. package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
  296. package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
  297. package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -36
  298. package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
  299. package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
  300. package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
  301. package/src/__tests__/volume-optics-oracle.unit.test.ts +85 -0
  302. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +655 -0
  303. package/src/__tests__/volumetric-fog-component.unit.test.ts +71 -0
  304. package/src/__tests__/volumetric-fog-composite-stage-readback.dawn.test.ts +376 -0
  305. package/src/__tests__/volumetric-fog-errors.unit.test.ts +51 -0
  306. package/src/__tests__/volumetric-fog-inspection.unit.test.ts +77 -0
  307. package/src/__tests__/volumetric-fog-light-capability.unit.test.ts +19 -0
  308. package/src/__tests__/volumetric-fog-light-consumers.integration.test.ts +18 -0
  309. package/src/__tests__/volumetric-fog-light-errors.unit.test.ts +17 -0
  310. package/src/__tests__/volumetric-fog-light-topology.unit.test.ts +21 -0
  311. package/src/__tests__/volumetric-fog-light-transaction.integration.test.ts +53 -0
  312. package/src/__tests__/volumetric-fog-m9-watcher.integration.test.ts +27 -0
  313. package/src/__tests__/volumetric-fog-point-light-owner.integration.test.ts +44 -0
  314. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +49 -0
  315. package/src/__tests__/volumetric-fog-point-spot-contract.unit.test.ts +28 -0
  316. package/src/__tests__/volumetric-fog-point-spot-lkg.integration.test.ts +65 -0
  317. package/src/__tests__/volumetric-fog-point-spot-selection.integration.test.ts +49 -0
  318. package/src/__tests__/volumetric-fog-point-spot-temporal.unit.test.ts +55 -0
  319. package/src/__tests__/volumetric-fog-projector-contract.unit.test.ts +22 -0
  320. package/src/__tests__/volumetric-fog-projector-inspection.unit.test.ts +12 -0
  321. package/src/__tests__/volumetric-fog-projector-surface-volume.integration.test.ts +11 -0
  322. package/src/__tests__/volumetric-fog-projector-transaction.integration.test.ts +26 -0
  323. package/src/__tests__/volumetric-fog-recovery.integration.test.ts +47 -0
  324. package/src/__tests__/volumetric-fog-selected-light-resolution.integration.test.ts +63 -0
  325. package/src/__tests__/volumetric-fog-spot-closure.integration.test.ts +26 -0
  326. package/src/__tests__/volumetric-fog-spot-contract.test-d.ts +21 -0
  327. package/src/__tests__/volumetric-fog-spot-contract.unit.test.ts +27 -0
  328. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +14 -0
  329. package/src/__tests__/volumetric-fog-spot-optics.integration.test.ts +29 -0
  330. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +550 -0
  331. package/src/__tests__/volumetric-fog-temporal-selected-light.unit.test.ts +33 -0
  332. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +45 -0
  333. package/src/__tests__/volumetric-fog-topology.unit.test.ts +237 -0
  334. package/src/__tests__/volumetric-fog-transparent.integration.test.ts +27 -0
  335. package/src/assembly/device-feature-admission.ts +73 -0
  336. package/src/assembly/directional-shadow-inspection.ts +122 -0
  337. package/src/assembly/factory.ts +1093 -246
  338. package/src/assembly/host-contract.ts +25 -0
  339. package/src/assembly/render-target-host.ts +847 -0
  340. package/src/assets/asset-decoders.ts +1 -1
  341. package/src/assets/render-asset-port.ts +7 -1
  342. package/src/capture/cube-views.ts +69 -0
  343. package/src/capture/scheduler.ts +265 -0
  344. package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
  345. package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
  346. package/src/components/camera.ts +4 -0
  347. package/src/components/cube-camera.ts +52 -0
  348. package/src/components/directional-light.ts +22 -2
  349. package/src/components/directional-shadow-filter.ts +57 -0
  350. package/src/components/index.ts +2 -0
  351. package/src/components/light-helpers.ts +85 -7
  352. package/src/components/reflection-probe.ts +49 -0
  353. package/src/components/spot-light.ts +22 -3
  354. package/src/device/gpu-residency.ts +168 -58
  355. package/src/environment/frame.ts +6 -24
  356. package/src/environment/lifecycle.ts +12 -0
  357. package/src/errors/render.ts +405 -143
  358. package/src/extract/directional-shadow-projection.ts +61 -0
  359. package/src/extract/environment.ts +57 -0
  360. package/src/extract/visibility.ts +25 -1
  361. package/src/features/fullscreen.ts +3 -0
  362. package/src/features/targets.ts +4 -1
  363. package/src/features/types.ts +10 -0
  364. package/src/fullscreen-post-process-pass.ts +43 -2
  365. package/src/gpu-driven/batch-topology.ts +1 -0
  366. package/src/gpu-driven/production-raster.ts +1 -3
  367. package/src/gpu-scene.ts +8 -1
  368. package/src/gpu-usage.ts +2 -0
  369. package/src/hdrp-buffers.ts +165 -59
  370. package/src/ibl/IblPipelineCache.ts +11 -0
  371. package/src/ibl/kernel-cache.ts +88 -0
  372. package/src/index.ts +186 -1
  373. package/src/inspection-types.ts +56 -0
  374. package/src/instances-derived-bounds.ts +171 -0
  375. package/src/light-buffer-layout.ts +74 -26
  376. package/src/mesh-material-bindings.ts +132 -0
  377. package/src/pbr-pipeline.ts +139 -27
  378. package/src/pipeline/standard-forward-lane.ts +65 -15
  379. package/src/pipeline/standard-lighting/errors.ts +6 -0
  380. package/src/pipeline/standard-lighting/graph.ts +157 -0
  381. package/src/pipeline/standard-lighting/inspection.ts +88 -0
  382. package/src/pipeline/standard-lighting/layout.ts +31 -0
  383. package/src/pipeline/standard-lighting/light-frame.ts +34 -0
  384. package/src/pipeline/standard-lighting/membership.ts +43 -0
  385. package/src/pipeline/standard-lighting/prepare.ts +37 -0
  386. package/src/pipeline/standard-lighting/topology.ts +120 -0
  387. package/src/pipeline/standard-lighting/transport.ts +77 -0
  388. package/src/pipeline/standard-pipeline.ts +141 -192
  389. package/src/pipeline/standard-post.ts +26 -7
  390. package/src/pipeline/standard-profile.ts +23 -30
  391. package/src/pipeline-spec.ts +84 -21
  392. package/src/point-shadow-inspection.ts +55 -0
  393. package/src/record/__tests__/temporal-payload.unit.test.ts +42 -1
  394. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
  395. package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
  396. package/src/record/frame-lighting.ts +470 -516
  397. package/src/record/frame-snapshot.ts +76 -28
  398. package/src/record/frame-targets.ts +23 -2
  399. package/src/record/frame.ts +1169 -79
  400. package/src/record/gpu-pass-timing/contract.ts +180 -0
  401. package/src/record/gpu-pass-timing/errors.ts +34 -0
  402. package/src/record/gpu-pass-timing/index.ts +37 -0
  403. package/src/record/gpu-pass-timing/parser.ts +97 -0
  404. package/src/record/gpu-pass-timing/session.ts +938 -0
  405. package/src/record/gpu-timing.ts +233 -0
  406. package/src/record/main-pass-geometry.ts +120 -80
  407. package/src/record/main-pass-material.ts +101 -11
  408. package/src/record/main-pass-sprite-draws.ts +54 -25
  409. package/src/record/main-pass.ts +71 -15
  410. package/src/record/render-context.ts +77 -0
  411. package/src/record/shadow-pass.ts +104 -66
  412. package/src/record/skybox-post-pass.ts +20 -4
  413. package/src/record/typed-frame-graph.ts +1016 -32
  414. package/src/record/view-ubo.ts +63 -28
  415. package/src/reflection/filter.ts +81 -0
  416. package/src/reflection/gpu-table.ts +44 -0
  417. package/src/reflection/projection.ts +281 -0
  418. package/src/render-contract.ts +147 -4
  419. package/src/render-data.ts +50 -22
  420. package/src/render-graph-primitives.ts +9 -4
  421. package/src/render-pipeline.ts +161 -2
  422. package/src/render-system-extract.ts +886 -103
  423. package/src/render-system.ts +1174 -66
  424. package/src/renderer-inspect.ts +66 -0
  425. package/src/renderer.ts +222 -0
  426. package/src/scene/render-scene.ts +117 -9
  427. package/src/shadow-atlas.ts +5 -5
  428. package/src/ssao-buffers.ts +9 -2
  429. package/src/targets/contracts.ts +182 -0
  430. package/src/targets/graph-projection.ts +169 -0
  431. package/src/targets/material-source.ts +143 -0
  432. package/src/targets/owner.ts +214 -0
  433. package/src/targets/physical.ts +18 -0
  434. package/src/targets/readback.ts +153 -0
  435. package/src/temporal/frame.ts +128 -0
  436. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +61 -23
  437. package/src/typed-render-graph-primitives.ts +34 -2
  438. package/src/typed-shadow-atlas.ts +17 -0
  439. package/src/typed-shadow-passes.ts +47 -40
  440. package/src/volume/capability.ts +173 -0
  441. package/src/volume/component.ts +110 -0
  442. package/src/volume/extract.ts +21 -0
  443. package/src/volume/inspection.ts +78 -0
  444. package/src/volume/passes.ts +686 -0
  445. package/src/volume/recovery.ts +86 -0
  446. package/src/volume/resources.ts +236 -0
  447. package/src/volume/temporal.ts +89 -0
  448. package/dist/chunk-IPXCABEP.mjs.map +0 -1
  449. package/dist/chunk-LOSO4CTV.mjs.map +0 -1
  450. package/dist/chunk-RJRUS55L.mjs.map +0 -1
  451. package/dist/chunk-YTQ5C7YQ.mjs +0 -584
  452. package/dist/chunk-YTQ5C7YQ.mjs.map +0 -1
@@ -116,54 +116,55 @@ export function createRenderSurfaceError(
116
116
  return new RenderSurfaceError(`surface-${kind}-failed` as SurfaceFailureCode, detail);
117
117
  }
118
118
 
119
+ export interface TemporalFrameSubmitDetail {
120
+ readonly reason: 'queue-submit-failed';
121
+ }
122
+
123
+ export class TemporalFrameSubmitError extends Error {
124
+ readonly code = 'temporal-frame-submit-rejected' as const;
125
+ readonly expected = 'the staged frame is accepted by queue.submit before temporal facts advance';
126
+ readonly hint = 'inspect the queue submission and retry the frame after the device is available';
127
+ readonly detail: TemporalFrameSubmitDetail;
128
+
129
+ constructor(reason: 'queue-submit-failed') {
130
+ super(`temporal-frame-submit-rejected: ${reason}`);
131
+ this.name = 'TemporalFrameSubmitError';
132
+ this.detail = { reason };
133
+ }
134
+ }
135
+
119
136
  // ── ShadowInvalidConfigError ──────────────────────────────────────────────
120
137
 
121
138
  /**
122
139
  * Detail for `RuntimeErrorCode 'shadow-invalid-config'`.
123
140
  *
124
- * Emitted by `DirectionalLight.validate` shadow-field path when a field value violates
125
- * runtime constraints (e.g. mapSize < 1, cascadeCount not in {1..4}).
126
- * AI users access `.detail.field` / `.detail.value` / `.detail.min` /
127
- * `.detail.max` via property access — no string parsing.
128
- *
129
- * `max` is `undefined` for lower-bound-only validations (e.g. mapSize < 1).
130
- * feat-20260613-csm: max added for upper-bound cascade validations
131
- * (cascadeCount max=4, splitLambda max=1, cascadeBlend max=0.5).
141
+ * The four fields are the only recovery surface: AI users read the invalid
142
+ * field, actual value, structured bound, and reason without parsing prose.
132
143
  */
144
+ export type ShadowInvalidConfigBound =
145
+ | { readonly kind: 'range'; readonly min: number; readonly max: number }
146
+ | { readonly kind: 'lower-bound'; readonly operator: '>' | '>='; readonly value: number }
147
+ | { readonly kind: 'allowed-values'; readonly values: readonly number[] };
148
+
133
149
  export interface ShadowInvalidConfigDetail {
134
150
  readonly field: string;
135
- readonly value: number;
136
- readonly min: number;
137
- readonly max?: number;
151
+ readonly actual: number;
152
+ readonly bound: ShadowInvalidConfigBound;
153
+ readonly reason: string;
138
154
  }
139
155
 
140
156
  /**
141
157
  * Structured error for shadow component config validation failures.
142
158
  *
143
- * Emitted by `DirectionalLight.validate()` shadow-field path (mapSize / cascadeCount /
144
- * splitLambda / cascadeBlend / shadowDistance) and `PointLightShadow.validate()`
145
- * (mapSize / farPlane > nearPlane / pcfKernelSize); both shadow component
146
- * types share this single error class so `switch (err.code)` on
147
- * `RuntimeErrorCode` only needs one branch (charter P4 — closed-union SSOT).
148
- * Four-field surface per AGENTS.md error model:
159
+ * Emitted by Directional, Point, and Spot shadow validation. All three
160
+ * component owners share this error class so `switch (err.code)` on
161
+ * `RuntimeErrorCode` needs one branch (charter P4 closed-union SSOT).
162
+ * Four-field surface:
149
163
  * - `.code = 'shadow-invalid-config'` (closed RuntimeErrorCode)
150
164
  * - `.expected` — expected-state description (programmatic predicate form)
151
165
  * - `.hint` — actionable recovery guidance (imperative; AI users paste into
152
- * spawn calls). Integer-typed fields (e.g. `cascadeCount`, `pcfKernelSize`)
153
- * get an "integer in [min, max]" hint; otherwise "[min, max]" range or
154
- * "<comparator> min".
155
- * - `.detail = { field, value, min, max? }` — structured values (charter P4)
156
- *
157
- * 4th constructor parameter is a union over the two range shapes:
158
- * - `number` — `max` for a closed `[min, max]` range (CSM cascadeCount /
159
- * splitLambda / cascadeBlend). hint uses "in [min, max]"; integer-typed
160
- * fields get "integer in [min, max]".
161
- * - `'>' | '>='` — comparator for an open lower-bound predicate. `'>'` is
162
- * used when `min` carries dynamic context (e.g. `farPlane > nearPlane` —
163
- * the surfaced hint reads "must be > nearPlane" so AI users setting
164
- * farPlane=nearPlane don't re-fail the spawn loop with the wrong cue).
165
- * - `undefined` — defaults to `'>='`. Callsites for mapSize < 1 validation
166
- * stay backward-compatible (3-arg form).
166
+ * spawn calls).
167
+ * - `.detail = { field, actual, bound, reason }` structured values.
167
168
  */
168
169
  export class ShadowInvalidConfigError extends Error {
169
170
  readonly code = 'shadow-invalid-config' as const;
@@ -171,35 +172,53 @@ export class ShadowInvalidConfigError extends Error {
171
172
  readonly hint: string;
172
173
  readonly detail: ShadowInvalidConfigDetail;
173
174
 
174
- constructor(field: string, value: number, min: number, maxOrComparator?: number | '>' | '>=') {
175
- const isComparator = maxOrComparator === '>' || maxOrComparator === '>=';
176
- const max = !isComparator && typeof maxOrComparator === 'number' ? maxOrComparator : undefined;
177
- const comparator: '>' | '>=' = isComparator ? (maxOrComparator as '>' | '>=') : '>=';
178
- // Integer-typed fields get an "integer in [min, max]" hint when a range
179
- // is supplied. Expand this set as new integer-typed shadow fields land.
180
- const isInteger = field === 'cascadeCount' || field === 'pcfKernelSize';
181
- // pcfKernelSize must be odd (kernel is symmetric around the center tap).
182
- // Naming "odd" in the hint stops an AI retry from looping min->min+1 (4->6).
183
- const isOdd = field === 'pcfKernelSize';
184
- const hint =
185
- max !== undefined
186
- ? isInteger
187
- ? `set ${field} to an integer in [${min}, ${max}]; got ${value}`
188
- : `set ${field} to a value in [${min}, ${max}]; got ${value}`
189
- : isOdd
190
- ? `set ${field} to an odd integer ${comparator} ${min}; got ${value}`
191
- : `set ${field} to a value ${comparator} ${min}; got ${value}`;
192
- const expected =
193
- max !== undefined ? `${field} in [${min}, ${max}]` : `${field} ${comparator} ${min}`;
194
- super(
195
- max !== undefined
196
- ? `shadow component .${field} must be in [${min}, ${max}], got ${value}`
197
- : `shadow component .${field} must be ${comparator} ${min}, got ${value}`,
198
- );
175
+ constructor(
176
+ field: string,
177
+ actual: number,
178
+ minOrBound: number | ShadowInvalidConfigBound,
179
+ maxOrComparator?: number | '>' | '>=',
180
+ reason?: string,
181
+ ) {
182
+ const bound: ShadowInvalidConfigBound =
183
+ typeof minOrBound === 'number'
184
+ ? typeof maxOrComparator === 'number'
185
+ ? { kind: 'range', min: minOrBound, max: maxOrComparator }
186
+ : {
187
+ kind: 'lower-bound',
188
+ operator: maxOrComparator === '>' ? '>' : '>=',
189
+ value: minOrBound,
190
+ }
191
+ : minOrBound;
192
+ const resolvedReason = reason ?? shadowBoundReason(bound);
193
+ const expected = shadowBoundExpected(field, bound);
194
+ const hint = `set ${field} to ${resolvedReason}; got ${actual}`;
195
+ super(`shadow component .${field} is invalid: ${resolvedReason}; got ${actual}`);
199
196
  this.name = 'ShadowInvalidConfigError';
200
197
  this.hint = hint;
201
198
  this.expected = expected;
202
- this.detail = { field, value, min, ...(max !== undefined ? { max } : {}) };
199
+ this.detail = { field, actual, bound, reason: resolvedReason };
200
+ }
201
+ }
202
+
203
+ function shadowBoundExpected(field: string, bound: ShadowInvalidConfigBound): string {
204
+ switch (bound.kind) {
205
+ case 'range':
206
+ return `${field} in [${bound.min}, ${bound.max}]`;
207
+ case 'lower-bound':
208
+ return `${field} ${bound.operator} ${bound.value}`;
209
+ case 'allowed-values':
210
+ return `${field} in {${bound.values.join(', ')}}`;
211
+ }
212
+ }
213
+
214
+ function shadowBoundReason(bound: ShadowInvalidConfigBound): string {
215
+ switch (bound.kind) {
216
+ case 'range':
217
+ return `a value in [${bound.min}, ${bound.max}]`;
218
+ case 'lower-bound':
219
+ return `a value ${bound.operator} ${bound.value}`;
220
+ case 'allowed-values':
221
+ return `one of [${bound.values.join(', ')}]`;
203
222
  }
204
223
  }
205
224
 
@@ -253,133 +272,125 @@ export class EquirectProjectionFailedError extends Error {
253
272
  }
254
273
  }
255
274
 
256
- // ── HdrpLightBudgetExceededError ───────────────────────────────────────────
275
+ // ── StandardLightBudgetExceededError ──────────────────────────────────────
257
276
 
258
- /**
259
- * Detail for `RuntimeErrorCode 'hdrp-light-budget-exceeded'`.
260
- *
261
- * Emitted per-frame (once-per-frame fire) when light count exceeds HDRP budget.
262
- */
263
- export interface HdrpLightBudgetExceededDetail {
277
+ /** The finite local-light budget that a Standard frame agreed to admit. */
278
+ export interface StandardLightBudgetExceededDetail {
264
279
  readonly actual: number;
265
280
  readonly budget: number;
266
281
  }
267
282
 
268
283
  /**
269
- * Structured error for HDRP light budget exceeded (AC-06/AC-07).
270
- *
271
- * Emitted per-frame in recordFrame when the total punctual light count
272
- * exceeds the HDRP budget (256). Fail-soft: fire once per frame, truncate to 256.
273
- * - `.code = 'hdrp-light-budget-exceeded'` (closed RuntimeErrorCode)
274
- * - `.expected` — 'light count <= 256'
275
- * - `.hint` — 'reduce world light count or increase budget (OOS-hdrp-larger-budget)'
276
- * - `.detail = { actual, budget }`
284
+ * Structured refusal for a Standard frame whose finite local-light set is
285
+ * outside the selected profile budget. The frame is rejected as a whole; the
286
+ * record owner must not slice the input or submit a partial membership set.
277
287
  */
278
- export class HdrpLightBudgetExceededError extends Error {
279
- readonly code = 'hdrp-light-budget-exceeded' as const;
288
+ export class StandardLightBudgetExceededError extends Error {
289
+ readonly code = 'standard-light-budget-exceeded' as const;
280
290
  readonly expected: string;
281
291
  readonly hint: string;
282
- readonly detail: HdrpLightBudgetExceededDetail;
292
+ readonly detail: StandardLightBudgetExceededDetail;
283
293
 
284
294
  constructor(actual: number, budget: number) {
285
295
  const expected = `light count <= ${budget}`;
286
296
  const hint =
287
- `${actual} lights exceed HDRP budget ${budget}; ` +
288
- 'truncating to 256. Reduce light count or wait for OOS-hdrp-larger-budget';
289
- super(`HDRP light budget exceeded: ${actual} > ${budget}`);
290
- this.name = 'HdrpLightBudgetExceededError';
297
+ `${actual} finite local lights exceed Standard budget ${budget}; ` +
298
+ 'reduce the local-light set or select a profile with a supported budget';
299
+ super(`Standard light budget exceeded: ${actual} > ${budget}`);
300
+ this.name = 'StandardLightBudgetExceededError';
291
301
  this.expected = expected;
292
302
  this.hint = hint;
293
303
  this.detail = { actual, budget };
294
304
  }
295
305
  }
296
306
 
297
- // ── HdrpIndexListOverflowError ─────────────────────────────────────────────
307
+ // ── StandardClusterIndexOverflowError ──────────────────────────────────────
298
308
 
299
- /**
300
- * Detail for `RuntimeErrorCode 'hdrp-index-list-overflow'`.
301
- *
302
- * Emitted per-frame (once-per-frame fire) when the cluster binner overflows
303
- * the light index list capacity (65536). Upgraded from ClusterBinError.
304
- */
305
- export interface HdrpIndexListOverflowDetail {
309
+ /** Cluster membership entries that could not fit the single shared index list. */
310
+ export interface StandardClusterIndexOverflowDetail {
306
311
  readonly actual: number;
307
312
  readonly capacity: number;
308
313
  }
309
314
 
310
315
  /**
311
- * Structured error for HDRP cluster binner index list overflow (AC-24).
312
- *
313
- * Emitted per-frame in recordFrame when the CPU binner returns
314
- * `ClusterBinError('index-overflow')`. Fail-soft: fire once per frame,
315
- * continue rendering with what fit.
316
- * - `.code = 'hdrp-index-list-overflow'` (closed RuntimeErrorCode)
317
- * - `.expected` — 'light index list entries <= 65536'
318
- * - `.hint` — 'reduce lights, shrink cluster grid, or increase capacity'
319
- * - `.detail = { actual, capacity }`
316
+ * Structured refusal for a membership producer that exceeded the shared
317
+ * Cluster index-list capacity. No truncated list is uploaded and no graph is
318
+ * submitted for the rejected frame.
320
319
  */
321
- export class HdrpIndexListOverflowError extends Error {
322
- readonly code = 'hdrp-index-list-overflow' as const;
320
+ export class StandardClusterIndexOverflowError extends Error {
321
+ readonly code = 'standard-cluster-index-overflow' as const;
323
322
  readonly expected: string;
324
323
  readonly hint: string;
325
- readonly detail: HdrpIndexListOverflowDetail;
324
+ readonly detail: StandardClusterIndexOverflowDetail;
326
325
 
327
326
  constructor(actual: number, capacity: number) {
328
327
  const expected = `light index list entries <= ${capacity}`;
329
328
  const hint =
330
329
  `cluster binner overflow: writeCount ${actual} exceeds capacity ${capacity}; ` +
331
- 'reduce lights, shrink cluster grid, or increase LIGHT_INDEX_LIST_CAPACITY';
332
- super(`HDRP index list overflow: ${actual} > ${capacity}`);
333
- this.name = 'HdrpIndexListOverflowError';
330
+ 'reduce finite local lights or choose a supported cluster layout';
331
+ super(`Standard cluster index list overflow: ${actual} > ${capacity}`);
332
+ this.name = 'StandardClusterIndexOverflowError';
334
333
  this.expected = expected;
335
334
  this.hint = hint;
336
335
  this.detail = { actual, capacity };
337
336
  }
338
337
  }
339
338
 
340
- // ── HdrpDeferredCapsInsufficientError ──────────────────────────────────────
339
+ // ── StandardClusterTransportUnavailableError ───────────────────────────────
341
340
 
342
- /**
343
- * Detail for `RuntimeErrorCode 'hdrp-deferred-caps-insufficient'`.
344
- *
345
- * Emitted when the Standard clustered lane has fewer than 4 color attachments,
346
- * meaning the deferred path cannot allocate 3 g-buffer color targets + depth.
347
- */
348
- export interface HdrpDeferredCapsInsufficientDetail {
349
- readonly actual: number;
350
- readonly expected: number;
341
+ export interface StandardClusterTransportUnavailableDetail {
342
+ readonly requested: number;
343
+ readonly admitted: 0;
351
344
  }
352
345
 
353
346
  /**
354
- * Structured error for deferred-path capability gate failure.
355
- *
356
- * Emitted during Standard clustered lane validation synchronous throw.
357
- * - `.code = 'hdrp-deferred-caps-insufficient'` (closed RuntimeErrorCode)
358
- * - `.expected` — 'maxColorAttachments >= 4'
359
- * - `.hint` — actionable guidance to upgrade browser or select URP
360
- * - `.detail = { actual, expected }`
361
- *
362
- * @see plan-strategy D-5 (capability validation, no silent fallback)
347
+ * Structured capability refusal. Standard never turns an unproven transport
348
+ * into a smaller direct-light lane; the caller receives the exact requested
349
+ * local-light count and an admitted count of zero.
363
350
  */
364
- export class HdrpDeferredCapsInsufficientError extends Error {
365
- readonly code = 'hdrp-deferred-caps-insufficient' as const;
366
- readonly expected: string;
351
+ export class StandardClusterTransportUnavailableError extends Error {
352
+ readonly code = 'standard-cluster-transport-unavailable' as const;
353
+ readonly expected = 'all requested local lights have a proven Cluster transport';
367
354
  readonly hint: string;
368
- readonly detail: HdrpDeferredCapsInsufficientDetail;
355
+ readonly detail: StandardClusterTransportUnavailableDetail;
369
356
 
370
- constructor(actual: number) {
371
- const _expected = 4;
372
- const _expectedStr = `maxColorAttachments >= ${_expected}`;
373
- const hint =
374
- `WebGPU maxColorAttachments = ${actual} (need >= ${_expected}). ` +
375
- 'Upgrade browser to latest Chrome/Edge/Safari, or use URP (forgeax::urp) instead of HDRP.';
376
- super(
377
- `HDRP deferred caps insufficient: maxColorAttachments = ${actual} (need >= ${_expected})`,
378
- );
379
- this.name = 'HdrpDeferredCapsInsufficientError';
380
- this.expected = _expectedStr;
357
+ constructor(
358
+ requested: number,
359
+ hint = 'enable a proven Cluster storage transport before drawing',
360
+ ) {
361
+ super(`Standard Cluster transport unavailable for ${requested} local lights`);
362
+ this.name = 'StandardClusterTransportUnavailableError';
381
363
  this.hint = hint;
382
- this.detail = { actual, expected: _expected };
364
+ this.detail = { requested, admitted: 0 };
365
+ }
366
+ }
367
+
368
+ // ── StandardProfileInvalidError ───────────────────────────────────────────
369
+
370
+ export interface StandardProfileInvalidDetail {
371
+ readonly field: string;
372
+ readonly actual: unknown;
373
+ }
374
+
375
+ /** Structured validation failure for the single Standard profile surface. */
376
+ export class StandardProfileInvalidError extends Error {
377
+ readonly code = 'standard-profile-invalid' as const;
378
+ readonly expected: string;
379
+ readonly hint: string;
380
+ readonly detail: StandardProfileInvalidDetail;
381
+
382
+ constructor(message: string, detail?: StandardProfileInvalidDetail) {
383
+ super(message);
384
+ this.name = 'StandardProfileInvalidError';
385
+ this.detail = detail ?? { field: 'profile', actual: message };
386
+ if (this.detail.field === 'clusterGrid') {
387
+ this.expected = 'clusterGrid.{x,y,z} each positive integer in [1, 64]';
388
+ this.hint =
389
+ 'set clusterGrid.x, clusterGrid.y, and clusterGrid.z to positive integers in [1, 64]';
390
+ } else {
391
+ this.expected = 'StandardProfile contains only supported fields and values';
392
+ this.hint = 'repair the Standard profile fields and retry setProfile';
393
+ }
383
394
  }
384
395
  }
385
396
 
@@ -435,7 +446,7 @@ export interface PointShadowAtlasBoundsViolationDetail {
435
446
  * - `.code = 'point-shadow-atlas-bounds-violation'`
436
447
  * - `.expected` — `0 <= layer < layers && 0 <= face < 6`
437
448
  * - `.hint` — clamp `shadowAtlasLayer` or face index before calling
438
- * `faceView`; the cap on layers is `PointLightShadow` cardinality (4)
449
+ * `faceView`; the layer cap is the renderer-owned ShadowAtlas capacity
439
450
  * - `.detail = { axis, value, max }` — discriminates layer vs face
440
451
  */
441
452
  export class PointShadowAtlasBoundsViolationError extends Error {
@@ -1514,6 +1525,248 @@ export class PointsLinesPrepareFailedError extends Error {
1514
1525
  }
1515
1526
  }
1516
1527
 
1528
+ // -- RenderTarget errors ------------------------------------------------------
1529
+
1530
+ export interface RenderTargetDescriptorInvalidDetail {
1531
+ readonly field: string;
1532
+ readonly value: unknown;
1533
+ readonly expected: string;
1534
+ }
1535
+
1536
+ export class RenderTargetDescriptorInvalidError extends Error {
1537
+ readonly code = 'render-target-descriptor-invalid' as const;
1538
+ readonly expected: string;
1539
+ readonly hint: string;
1540
+ readonly detail: RenderTargetDescriptorInvalidDetail;
1541
+
1542
+ constructor(detail: RenderTargetDescriptorInvalidDetail) {
1543
+ super(`render-target-descriptor-invalid: ${detail.field} does not satisfy ${detail.expected}`);
1544
+ this.name = 'RenderTargetDescriptorInvalidError';
1545
+ this.expected = detail.expected;
1546
+ this.hint = `set RenderTargetDescriptor.${detail.field} to the expected value, then retry create or resize`;
1547
+ this.detail = detail;
1548
+ }
1549
+ }
1550
+
1551
+ export interface RenderTargetCapabilityMissingDetail {
1552
+ readonly operation: 'create' | 'resize' | 'source' | 'readback';
1553
+ readonly requested: string;
1554
+ readonly capability: string;
1555
+ readonly actual: string;
1556
+ }
1557
+
1558
+ export class RenderTargetCapabilityMissingError extends Error {
1559
+ readonly code = 'render-target-capability-missing' as const;
1560
+ readonly expected: string;
1561
+ readonly hint: string;
1562
+ readonly detail: RenderTargetCapabilityMissingDetail;
1563
+
1564
+ constructor(detail: RenderTargetCapabilityMissingDetail) {
1565
+ super(
1566
+ `render-target-capability-missing: ${detail.capability} does not admit ${detail.requested}`,
1567
+ );
1568
+ this.name = 'RenderTargetCapabilityMissingError';
1569
+ this.expected = `${detail.capability} admits ${detail.requested}`;
1570
+ this.hint = `choose an admitted target descriptor or use a backend providing ${detail.capability}`;
1571
+ this.detail = detail;
1572
+ }
1573
+ }
1574
+
1575
+ export type RenderTargetStateInvalidReason =
1576
+ | 'foreign-renderer'
1577
+ | 'destroyed'
1578
+ | 'uninitialized'
1579
+ | 'generation-mismatch'
1580
+ | 'readback-without-intent';
1581
+
1582
+ export interface RenderTargetStateInvalidDetail {
1583
+ readonly operation: 'inspect' | 'resize' | 'source' | 'readback' | 'destroy';
1584
+ readonly reason: RenderTargetStateInvalidReason;
1585
+ readonly state: 'uninitialized' | 'candidate' | 'active' | 'rebuilding' | 'destroyed';
1586
+ readonly generation: number;
1587
+ }
1588
+
1589
+ export class RenderTargetStateInvalidError extends Error {
1590
+ readonly code = 'render-target-state-invalid' as const;
1591
+ readonly expected: string;
1592
+ readonly hint: string;
1593
+ readonly detail: RenderTargetStateInvalidDetail;
1594
+
1595
+ constructor(detail: RenderTargetStateInvalidDetail) {
1596
+ super(`render-target-state-invalid: ${detail.operation} cannot use ${detail.reason}`);
1597
+ this.name = 'RenderTargetStateInvalidError';
1598
+ this.expected = `target state permits ${detail.operation}`;
1599
+ this.hint =
1600
+ 'use the Renderer that created the target, then initialize, recover, or stop using the destroyed token';
1601
+ this.detail = detail;
1602
+ }
1603
+ }
1604
+
1605
+ export interface RenderTargetOperationFailedDetail {
1606
+ readonly operation: 'create' | 'resize' | 'source' | 'readback' | 'destroy' | 'recover';
1607
+ readonly stage: 'allocation' | 'compile' | 'write' | 'submit' | 'copy' | 'retire';
1608
+ readonly generation: number;
1609
+ readonly cause: unknown;
1610
+ readonly recovery: 'retry' | 'recover' | 'retain-last-known-good';
1611
+ }
1612
+
1613
+ export class RenderTargetOperationFailedError extends Error {
1614
+ readonly code = 'render-target-operation-failed' as const;
1615
+ readonly expected: string;
1616
+ readonly hint: string;
1617
+ readonly detail: RenderTargetOperationFailedDetail;
1618
+
1619
+ constructor(detail: RenderTargetOperationFailedDetail) {
1620
+ super(`render-target-operation-failed: ${detail.operation} failed during ${detail.stage}`);
1621
+ this.name = 'RenderTargetOperationFailedError';
1622
+ this.expected = `${detail.operation} completes ${detail.stage}`;
1623
+ this.hint =
1624
+ 'inspect detail.cause, then retry, recover the Renderer, or retain the last-known-good generation';
1625
+ this.detail = detail;
1626
+ }
1627
+ }
1628
+
1629
+ export interface ReflectionProbeBudgetExceededDetail {
1630
+ readonly actual: number;
1631
+ readonly budget: number;
1632
+ }
1633
+
1634
+ export class ReflectionProbeBudgetExceededError extends Error {
1635
+ readonly code = 'reflection-probe-budget-exceeded' as const;
1636
+ readonly expected: string;
1637
+ readonly hint: string;
1638
+ readonly detail: ReflectionProbeBudgetExceededDetail;
1639
+
1640
+ constructor(actual: number, budget: number) {
1641
+ super(`reflection-probe-budget-exceeded: ${actual} > ${budget}`);
1642
+ this.name = 'ReflectionProbeBudgetExceededError';
1643
+ this.expected = `reflection probe work <= ${budget}`;
1644
+ this.hint = 'reduce probe updates for this frame or raise the RenderProfile probe budget';
1645
+ this.detail = { actual, budget };
1646
+ }
1647
+ }
1648
+
1649
+ export interface RenderIntentInvalidDetail {
1650
+ readonly component: 'CubeCamera' | 'ReflectionProbe';
1651
+ readonly field: 'updateIntent';
1652
+ readonly value: number;
1653
+ readonly allowed: readonly [0, 1, 2];
1654
+ }
1655
+
1656
+ export class RenderIntentInvalidError extends Error {
1657
+ readonly code = 'render-intent-invalid' as const;
1658
+ readonly expected: string;
1659
+ readonly hint: string;
1660
+ readonly detail: RenderIntentInvalidDetail;
1661
+
1662
+ constructor(component: RenderIntentInvalidDetail['component'], value: number) {
1663
+ super(`render-intent-invalid: ${component}.updateIntent is not an admitted value`);
1664
+ this.name = 'RenderIntentInvalidError';
1665
+ this.expected = `${component}.updateIntent is one of 0, 1, or 2`;
1666
+ this.hint = `set ${component}.updateIntent to 0, 1, or 2`;
1667
+ this.detail = { component, field: 'updateIntent', value, allowed: [0, 1, 2] };
1668
+ }
1669
+ }
1670
+
1671
+ export interface VolumeOwnerConflictDetail {
1672
+ readonly ownerCount: number;
1673
+ }
1674
+
1675
+ export class VolumeOwnerConflictError extends Error {
1676
+ readonly code = 'volume-owner-conflict' as const;
1677
+ readonly expected = 'exactly one global VolumetricFog owner is authored';
1678
+ readonly hint = 'remove additional VolumetricFog owners and retry extraction';
1679
+ readonly detail: VolumeOwnerConflictDetail;
1680
+
1681
+ constructor(ownerCount: number) {
1682
+ super(`volume-owner-conflict: received ${ownerCount} owners`);
1683
+ this.name = 'VolumeOwnerConflictError';
1684
+ this.detail = { ownerCount };
1685
+ }
1686
+ }
1687
+
1688
+ export interface VolumeDensityShapeMismatchDetail {
1689
+ readonly guid: string;
1690
+ readonly viewDimension: string;
1691
+ }
1692
+
1693
+ export class VolumeDensityShapeMismatchError extends Error {
1694
+ readonly code = 'volume-density-shape-mismatch' as const;
1695
+ readonly expected = 'density is a linear 3D TextureAsset';
1696
+ readonly hint = 'bind a verified linear texture with viewDimension 3d';
1697
+ readonly detail: VolumeDensityShapeMismatchDetail;
1698
+
1699
+ constructor(guid: string, viewDimension: string) {
1700
+ super(`volume-density-shape-mismatch: ${viewDimension} density is not 3d`);
1701
+ this.name = 'VolumeDensityShapeMismatchError';
1702
+ this.detail = { guid, viewDimension };
1703
+ }
1704
+ }
1705
+
1706
+ export interface VolumeInvalidBoundsDetail {
1707
+ readonly min: readonly [number, number, number];
1708
+ readonly max: readonly [number, number, number];
1709
+ }
1710
+
1711
+ export class VolumeInvalidBoundsError extends Error {
1712
+ readonly code = 'volume-invalid-bounds' as const;
1713
+ readonly expected = 'bounds are finite and max is greater than min on every axis';
1714
+ readonly hint = 'set finite non-degenerate volume bounds';
1715
+ readonly detail: VolumeInvalidBoundsDetail;
1716
+
1717
+ constructor(bounds: VolumeInvalidBoundsDetail) {
1718
+ super('volume-invalid-bounds: bounds must be finite and non-degenerate');
1719
+ this.name = 'VolumeInvalidBoundsError';
1720
+ this.detail = bounds;
1721
+ }
1722
+ }
1723
+
1724
+ export interface VolumeInvalidParametersDetail {
1725
+ readonly field: string;
1726
+ readonly value: unknown;
1727
+ }
1728
+
1729
+ export class VolumeInvalidParametersError extends Error {
1730
+ readonly code = 'volume-invalid-parameters' as const;
1731
+ readonly expected = 'volume parameters remain finite and inside their closed ranges';
1732
+ readonly hint = 'repair extinction, albedo, emission, anisotropy, or maxDistance';
1733
+ readonly detail: VolumeInvalidParametersDetail;
1734
+
1735
+ constructor(input: { readonly maxDistance?: number; readonly anisotropy?: number }) {
1736
+ const field =
1737
+ input.maxDistance !== undefined && input.maxDistance <= 0 ? 'maxDistance' : 'parameters';
1738
+ const value = field === 'maxDistance' ? input.maxDistance : input.anisotropy;
1739
+ super(`volume-invalid-parameters: ${field} is outside the authored range`);
1740
+ this.name = 'VolumeInvalidParametersError';
1741
+ this.detail = { field, value };
1742
+ }
1743
+ }
1744
+
1745
+ export type VolumeError =
1746
+ | VolumeOwnerConflictError
1747
+ | VolumeDensityShapeMismatchError
1748
+ | VolumeInvalidBoundsError
1749
+ | VolumeInvalidParametersError;
1750
+
1751
+ export interface ProjectorBindingDetail {
1752
+ readonly guid: string;
1753
+ readonly status: 'pending' | 'invalid' | 'bind-failed';
1754
+ }
1755
+
1756
+ export class ProjectorBindingError extends Error {
1757
+ readonly code = 'projector-binding-failed' as const;
1758
+ readonly expected = 'authored projector is accepted and bound for both surface and volume';
1759
+ readonly hint =
1760
+ 'inspect the projector Meta/Pack receipt, repair the source, and retry with the same GUID';
1761
+ readonly detail: ProjectorBindingDetail;
1762
+
1763
+ constructor(guid: string, status: ProjectorBindingDetail['status']) {
1764
+ super(`projector binding failed for ${guid}: ${status}`);
1765
+ this.name = 'ProjectorBindingError';
1766
+ this.detail = { guid, status };
1767
+ }
1768
+ }
1769
+
1517
1770
  // -- RenderErrorCode / RenderError closed unions --------------------------------
1518
1771
 
1519
1772
  /**
@@ -1536,9 +1789,10 @@ export type RenderError =
1536
1789
  | TaaUnavailableError
1537
1790
  | ShadowInvalidConfigError
1538
1791
  | EquirectProjectionFailedError
1539
- | HdrpLightBudgetExceededError
1540
- | HdrpIndexListOverflowError
1541
- | HdrpDeferredCapsInsufficientError
1792
+ | StandardLightBudgetExceededError
1793
+ | StandardClusterIndexOverflowError
1794
+ | StandardClusterTransportUnavailableError
1795
+ | StandardProfileInvalidError
1542
1796
  | PointShadowAtlasUninitializedError
1543
1797
  | PointShadowAtlasBoundsViolationError
1544
1798
  | VideoUploadUnsupportedError
@@ -1566,4 +1820,12 @@ export type RenderError =
1566
1820
  | PointsLinesStyleUnsupportedError
1567
1821
  | PointsLinesMaterialUnsupportedError
1568
1822
  | PointsLinesBudgetExceededError
1569
- | PointsLinesPrepareFailedError;
1823
+ | PointsLinesPrepareFailedError
1824
+ | RenderTargetDescriptorInvalidError
1825
+ | RenderTargetCapabilityMissingError
1826
+ | RenderTargetStateInvalidError
1827
+ | RenderTargetOperationFailedError
1828
+ | ReflectionProbeBudgetExceededError
1829
+ | RenderIntentInvalidError
1830
+ | ProjectorBindingError
1831
+ | VolumeError;