@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
@@ -1,4 +1,57 @@
1
1
  import { err, ok } from '@forgeax/engine-types';
2
+ import { cubeArrayDepthDescriptor, comparisonSamplerDescriptor, cubeArrayDepthFaceView } from '@forgeax/engine-rhi';
3
+
4
+ // src/ibl/kernel-cache.ts
5
+ var REFLECTION_PROBE_IBL_STAGES = ["raw", "filtered", "publish"];
6
+ var kernelCaches = /* @__PURE__ */ new Map();
7
+ function createIblKernelCache(generation) {
8
+ const existing = kernelCaches.get(generation);
9
+ if (existing !== void 0) return existing;
10
+ const created = {
11
+ generation,
12
+ pipelineIdentity: {},
13
+ samplerIdentity: {},
14
+ brdfLutIdentity: {}
15
+ };
16
+ kernelCaches.set(generation, created);
17
+ return created;
18
+ }
19
+ function createProbeIblOutput(input) {
20
+ return {
21
+ ...input,
22
+ raw: {},
23
+ filtered: {},
24
+ rawGeneration: 0,
25
+ filteredGeneration: 0,
26
+ lkg: true
27
+ };
28
+ }
29
+ function beginProbeIblUpdate(output) {
30
+ return {
31
+ ...output,
32
+ stages: REFLECTION_PROBE_IBL_STAGES,
33
+ nextStage: "raw",
34
+ candidateGeneration: output.filteredGeneration + 1
35
+ };
36
+ }
37
+ function publishProbeIblOutput(update, result) {
38
+ if (!result.ok || result.stage !== update.nextStage) return update;
39
+ if (result.stage === "raw") {
40
+ return {
41
+ ...update,
42
+ rawGeneration: update.candidateGeneration
43
+ };
44
+ }
45
+ if (result.stage === "filtered") return update;
46
+ return {
47
+ ...update,
48
+ filteredGeneration: update.candidateGeneration,
49
+ lkg: true
50
+ };
51
+ }
52
+ function resetIblKernelCaches() {
53
+ kernelCaches.clear();
54
+ }
2
55
 
3
56
  // src/errors/render.ts
4
57
  var LifecycleConstructionError = class extends Error {
@@ -12,28 +65,58 @@ var LifecycleConstructionError = class extends Error {
12
65
  this.detail = detail;
13
66
  }
14
67
  };
68
+ var TemporalFrameSubmitError = class extends Error {
69
+ code = "temporal-frame-submit-rejected";
70
+ expected = "the staged frame is accepted by queue.submit before temporal facts advance";
71
+ hint = "inspect the queue submission and retry the frame after the device is available";
72
+ detail;
73
+ constructor(reason) {
74
+ super(`temporal-frame-submit-rejected: ${reason}`);
75
+ this.name = "TemporalFrameSubmitError";
76
+ this.detail = { reason };
77
+ }
78
+ };
15
79
  var ShadowInvalidConfigError = class extends Error {
16
80
  code = "shadow-invalid-config";
17
81
  expected;
18
82
  hint;
19
83
  detail;
20
- constructor(field, value, min, maxOrComparator) {
21
- const isComparator = maxOrComparator === ">" || maxOrComparator === ">=";
22
- const max = !isComparator && typeof maxOrComparator === "number" ? maxOrComparator : void 0;
23
- const comparator = isComparator ? maxOrComparator : ">=";
24
- const isInteger = field === "cascadeCount" || field === "pcfKernelSize";
25
- const isOdd = field === "pcfKernelSize";
26
- const hint = max !== void 0 ? isInteger ? `set ${field} to an integer in [${min}, ${max}]; got ${value}` : `set ${field} to a value in [${min}, ${max}]; got ${value}` : isOdd ? `set ${field} to an odd integer ${comparator} ${min}; got ${value}` : `set ${field} to a value ${comparator} ${min}; got ${value}`;
27
- const expected = max !== void 0 ? `${field} in [${min}, ${max}]` : `${field} ${comparator} ${min}`;
28
- super(
29
- max !== void 0 ? `shadow component .${field} must be in [${min}, ${max}], got ${value}` : `shadow component .${field} must be ${comparator} ${min}, got ${value}`
30
- );
84
+ constructor(field, actual, minOrBound, maxOrComparator, reason) {
85
+ const bound = typeof minOrBound === "number" ? typeof maxOrComparator === "number" ? { kind: "range", min: minOrBound, max: maxOrComparator } : {
86
+ kind: "lower-bound",
87
+ operator: maxOrComparator === ">" ? ">" : ">=",
88
+ value: minOrBound
89
+ } : minOrBound;
90
+ const resolvedReason = reason ?? shadowBoundReason(bound);
91
+ const expected = shadowBoundExpected(field, bound);
92
+ const hint = `set ${field} to ${resolvedReason}; got ${actual}`;
93
+ super(`shadow component .${field} is invalid: ${resolvedReason}; got ${actual}`);
31
94
  this.name = "ShadowInvalidConfigError";
32
95
  this.hint = hint;
33
96
  this.expected = expected;
34
- this.detail = { field, value, min, ...max !== void 0 ? { max } : {} };
97
+ this.detail = { field, actual, bound, reason: resolvedReason };
35
98
  }
36
99
  };
100
+ function shadowBoundExpected(field, bound) {
101
+ switch (bound.kind) {
102
+ case "range":
103
+ return `${field} in [${bound.min}, ${bound.max}]`;
104
+ case "lower-bound":
105
+ return `${field} ${bound.operator} ${bound.value}`;
106
+ case "allowed-values":
107
+ return `${field} in {${bound.values.join(", ")}}`;
108
+ }
109
+ }
110
+ function shadowBoundReason(bound) {
111
+ switch (bound.kind) {
112
+ case "range":
113
+ return `a value in [${bound.min}, ${bound.max}]`;
114
+ case "lower-bound":
115
+ return `a value ${bound.operator} ${bound.value}`;
116
+ case "allowed-values":
117
+ return `one of [${bound.values.join(", ")}]`;
118
+ }
119
+ }
37
120
  var EquirectProjectionFailedError = class extends Error {
38
121
  code = "equirect-projection-failed";
39
122
  expected;
@@ -49,52 +132,64 @@ var EquirectProjectionFailedError = class extends Error {
49
132
  this.detail = { handle };
50
133
  }
51
134
  };
52
- var HdrpLightBudgetExceededError = class extends Error {
53
- code = "hdrp-light-budget-exceeded";
135
+ var StandardLightBudgetExceededError = class extends Error {
136
+ code = "standard-light-budget-exceeded";
54
137
  expected;
55
138
  hint;
56
139
  detail;
57
140
  constructor(actual, budget) {
58
141
  const expected = `light count <= ${budget}`;
59
- const hint = `${actual} lights exceed HDRP budget ${budget}; truncating to 256. Reduce light count or wait for OOS-hdrp-larger-budget`;
60
- super(`HDRP light budget exceeded: ${actual} > ${budget}`);
61
- this.name = "HdrpLightBudgetExceededError";
142
+ const hint = `${actual} finite local lights exceed Standard budget ${budget}; reduce the local-light set or select a profile with a supported budget`;
143
+ super(`Standard light budget exceeded: ${actual} > ${budget}`);
144
+ this.name = "StandardLightBudgetExceededError";
62
145
  this.expected = expected;
63
146
  this.hint = hint;
64
147
  this.detail = { actual, budget };
65
148
  }
66
149
  };
67
- var HdrpIndexListOverflowError = class extends Error {
68
- code = "hdrp-index-list-overflow";
150
+ var StandardClusterIndexOverflowError = class extends Error {
151
+ code = "standard-cluster-index-overflow";
69
152
  expected;
70
153
  hint;
71
154
  detail;
72
155
  constructor(actual, capacity) {
73
156
  const expected = `light index list entries <= ${capacity}`;
74
- const hint = `cluster binner overflow: writeCount ${actual} exceeds capacity ${capacity}; reduce lights, shrink cluster grid, or increase LIGHT_INDEX_LIST_CAPACITY`;
75
- super(`HDRP index list overflow: ${actual} > ${capacity}`);
76
- this.name = "HdrpIndexListOverflowError";
157
+ const hint = `cluster binner overflow: writeCount ${actual} exceeds capacity ${capacity}; reduce finite local lights or choose a supported cluster layout`;
158
+ super(`Standard cluster index list overflow: ${actual} > ${capacity}`);
159
+ this.name = "StandardClusterIndexOverflowError";
77
160
  this.expected = expected;
78
161
  this.hint = hint;
79
162
  this.detail = { actual, capacity };
80
163
  }
81
164
  };
82
- var HdrpDeferredCapsInsufficientError = class extends Error {
83
- code = "hdrp-deferred-caps-insufficient";
84
- expected;
165
+ var StandardClusterTransportUnavailableError = class extends Error {
166
+ code = "standard-cluster-transport-unavailable";
167
+ expected = "all requested local lights have a proven Cluster transport";
85
168
  hint;
86
169
  detail;
87
- constructor(actual) {
88
- const _expected = 4;
89
- const _expectedStr = `maxColorAttachments >= ${_expected}`;
90
- const hint = `WebGPU maxColorAttachments = ${actual} (need >= ${_expected}). Upgrade browser to latest Chrome/Edge/Safari, or use URP (forgeax::urp) instead of HDRP.`;
91
- super(
92
- `HDRP deferred caps insufficient: maxColorAttachments = ${actual} (need >= ${_expected})`
93
- );
94
- this.name = "HdrpDeferredCapsInsufficientError";
95
- this.expected = _expectedStr;
170
+ constructor(requested, hint = "enable a proven Cluster storage transport before drawing") {
171
+ super(`Standard Cluster transport unavailable for ${requested} local lights`);
172
+ this.name = "StandardClusterTransportUnavailableError";
96
173
  this.hint = hint;
97
- this.detail = { actual, expected: _expected };
174
+ this.detail = { requested, admitted: 0 };
175
+ }
176
+ };
177
+ var StandardProfileInvalidError = class extends Error {
178
+ code = "standard-profile-invalid";
179
+ expected;
180
+ hint;
181
+ detail;
182
+ constructor(message, detail) {
183
+ super(message);
184
+ this.name = "StandardProfileInvalidError";
185
+ this.detail = detail ?? { field: "profile", actual: message };
186
+ if (this.detail.field === "clusterGrid") {
187
+ this.expected = "clusterGrid.{x,y,z} each positive integer in [1, 64]";
188
+ this.hint = "set clusterGrid.x, clusterGrid.y, and clusterGrid.z to positive integers in [1, 64]";
189
+ } else {
190
+ this.expected = "StandardProfile contains only supported fields and values";
191
+ this.hint = "repair the Standard profile fields and retry setProfile";
192
+ }
98
193
  }
99
194
  };
100
195
  var PointShadowAtlasUninitializedError = class extends Error {
@@ -591,6 +686,119 @@ var PointsLinesPrepareFailedError = class extends Error {
591
686
  this.detail = detail;
592
687
  }
593
688
  };
689
+ var RenderTargetDescriptorInvalidError = class extends Error {
690
+ code = "render-target-descriptor-invalid";
691
+ expected;
692
+ hint;
693
+ detail;
694
+ constructor(detail) {
695
+ super(`render-target-descriptor-invalid: ${detail.field} does not satisfy ${detail.expected}`);
696
+ this.name = "RenderTargetDescriptorInvalidError";
697
+ this.expected = detail.expected;
698
+ this.hint = `set RenderTargetDescriptor.${detail.field} to the expected value, then retry create or resize`;
699
+ this.detail = detail;
700
+ }
701
+ };
702
+ var RenderTargetCapabilityMissingError = class extends Error {
703
+ code = "render-target-capability-missing";
704
+ expected;
705
+ hint;
706
+ detail;
707
+ constructor(detail) {
708
+ super(
709
+ `render-target-capability-missing: ${detail.capability} does not admit ${detail.requested}`
710
+ );
711
+ this.name = "RenderTargetCapabilityMissingError";
712
+ this.expected = `${detail.capability} admits ${detail.requested}`;
713
+ this.hint = `choose an admitted target descriptor or use a backend providing ${detail.capability}`;
714
+ this.detail = detail;
715
+ }
716
+ };
717
+ var RenderTargetStateInvalidError = class extends Error {
718
+ code = "render-target-state-invalid";
719
+ expected;
720
+ hint;
721
+ detail;
722
+ constructor(detail) {
723
+ super(`render-target-state-invalid: ${detail.operation} cannot use ${detail.reason}`);
724
+ this.name = "RenderTargetStateInvalidError";
725
+ this.expected = `target state permits ${detail.operation}`;
726
+ this.hint = "use the Renderer that created the target, then initialize, recover, or stop using the destroyed token";
727
+ this.detail = detail;
728
+ }
729
+ };
730
+ var RenderTargetOperationFailedError = class extends Error {
731
+ code = "render-target-operation-failed";
732
+ expected;
733
+ hint;
734
+ detail;
735
+ constructor(detail) {
736
+ super(`render-target-operation-failed: ${detail.operation} failed during ${detail.stage}`);
737
+ this.name = "RenderTargetOperationFailedError";
738
+ this.expected = `${detail.operation} completes ${detail.stage}`;
739
+ this.hint = "inspect detail.cause, then retry, recover the Renderer, or retain the last-known-good generation";
740
+ this.detail = detail;
741
+ }
742
+ };
743
+ var RenderIntentInvalidError = class extends Error {
744
+ code = "render-intent-invalid";
745
+ expected;
746
+ hint;
747
+ detail;
748
+ constructor(component, value) {
749
+ super(`render-intent-invalid: ${component}.updateIntent is not an admitted value`);
750
+ this.name = "RenderIntentInvalidError";
751
+ this.expected = `${component}.updateIntent is one of 0, 1, or 2`;
752
+ this.hint = `set ${component}.updateIntent to 0, 1, or 2`;
753
+ this.detail = { component, field: "updateIntent", value, allowed: [0, 1, 2] };
754
+ }
755
+ };
756
+ var VolumeOwnerConflictError = class extends Error {
757
+ code = "volume-owner-conflict";
758
+ expected = "exactly one global VolumetricFog owner is authored";
759
+ hint = "remove additional VolumetricFog owners and retry extraction";
760
+ detail;
761
+ constructor(ownerCount) {
762
+ super(`volume-owner-conflict: received ${ownerCount} owners`);
763
+ this.name = "VolumeOwnerConflictError";
764
+ this.detail = { ownerCount };
765
+ }
766
+ };
767
+ var VolumeDensityShapeMismatchError = class extends Error {
768
+ code = "volume-density-shape-mismatch";
769
+ expected = "density is a linear 3D TextureAsset";
770
+ hint = "bind a verified linear texture with viewDimension 3d";
771
+ detail;
772
+ constructor(guid, viewDimension) {
773
+ super(`volume-density-shape-mismatch: ${viewDimension} density is not 3d`);
774
+ this.name = "VolumeDensityShapeMismatchError";
775
+ this.detail = { guid, viewDimension };
776
+ }
777
+ };
778
+ var VolumeInvalidBoundsError = class extends Error {
779
+ code = "volume-invalid-bounds";
780
+ expected = "bounds are finite and max is greater than min on every axis";
781
+ hint = "set finite non-degenerate volume bounds";
782
+ detail;
783
+ constructor(bounds) {
784
+ super("volume-invalid-bounds: bounds must be finite and non-degenerate");
785
+ this.name = "VolumeInvalidBoundsError";
786
+ this.detail = bounds;
787
+ }
788
+ };
789
+ var VolumeInvalidParametersError = class extends Error {
790
+ code = "volume-invalid-parameters";
791
+ expected = "volume parameters remain finite and inside their closed ranges";
792
+ hint = "repair extinction, albedo, emission, anisotropy, or maxDistance";
793
+ detail;
794
+ constructor(input) {
795
+ const field = input.maxDistance !== void 0 && input.maxDistance <= 0 ? "maxDistance" : "parameters";
796
+ const value = field === "maxDistance" ? input.maxDistance : input.anisotropy;
797
+ super(`volume-invalid-parameters: ${field} is outside the authored range`);
798
+ this.name = "VolumeInvalidParametersError";
799
+ this.detail = { field, value };
800
+ }
801
+ };
594
802
 
595
803
  // src/temporal/scene-data.ts
596
804
  var SCENE_DATA_TEMPORAL_V1_SCHEMA = "forgeax::scene-data::temporal-v1";
@@ -786,13 +994,28 @@ function createSceneDataCatalog(options) {
786
994
  };
787
995
  }
788
996
 
789
- // src/pipeline/standard-profile.ts
790
- var STANDARD_PIPELINE_ID = "forgeax::standard";
791
- var STANDARD_LIGHT_COUNTS = [1, 32, 256];
997
+ // src/pipeline/standard-lighting/layout.ts
792
998
  var DEFAULT_CLUSTER_GRID = { x: 16, y: 9, z: 24 };
793
999
  var CLUSTER_GRID_STRIDE_U32 = 2;
794
1000
  var LIGHT_INDEX_LIST_CAPACITY = 1048576;
795
1001
  var MAX_LIGHTS = 256;
1002
+ function createStandardClusterLayout(grid = DEFAULT_CLUSTER_GRID) {
1003
+ const clusterCount = grid.x * grid.y * grid.z;
1004
+ return Object.freeze({
1005
+ grid,
1006
+ clusterCount,
1007
+ clusterGridStrideU32: CLUSTER_GRID_STRIDE_U32,
1008
+ clusterGridU32Length: clusterCount * CLUSTER_GRID_STRIDE_U32,
1009
+ lightIndexListCapacity: LIGHT_INDEX_LIST_CAPACITY,
1010
+ lightDataSlotCount: MAX_LIGHTS,
1011
+ lightBoundsInt32Length: MAX_LIGHTS * 6
1012
+ });
1013
+ }
1014
+ createStandardClusterLayout();
1015
+
1016
+ // src/pipeline/standard-profile.ts
1017
+ var STANDARD_PIPELINE_ID = "forgeax::standard";
1018
+ var STANDARD_LIGHT_COUNTS = [1, 32, 256];
796
1019
  var STANDARD_POST_STAGE_NAMES = [
797
1020
  "transparent-blend",
798
1021
  "bloom",
@@ -804,21 +1027,175 @@ var STANDARD_POST_STAGE_NAMES = [
804
1027
  var DEFAULT_STANDARD_PROFILE = Object.freeze({
805
1028
  pipelineId: STANDARD_PIPELINE_ID,
806
1029
  lightCount: 32,
807
- lighting: "direct",
1030
+ renderPath: "forward",
808
1031
  shadows: "filtered",
809
1032
  pbr: true,
810
1033
  ibl: true,
811
1034
  ssao: false,
812
- fallback: "native",
813
1035
  postStages: STANDARD_POST_STAGE_NAMES
814
1036
  });
815
- function resolveStandardLane(profile, capabilities) {
816
- if (!capabilities.compute || !capabilities.storageBuffer) return "cpu-webgl2";
817
- return profile.lighting;
1037
+ function resolveVolumetricFogProfile(profile) {
1038
+ return profile.volumetricFog ?? { quality: "high", depth: 64, tileSize: 4 };
818
1039
  }
819
1040
 
1041
+ // src/gpu-texture-usage.ts
1042
+ var GPU_TEXTURE_USAGE_COPY_SRC = 1;
1043
+ var GPU_TEXTURE_USAGE_COPY_DST = 2;
1044
+ var GPU_TEXTURE_USAGE_TEXTURE_BINDING = 4;
1045
+ var GPU_TEXTURE_USAGE_RENDER_ATTACHMENT = 16;
1046
+ var GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING = GPU_TEXTURE_USAGE_RENDER_ATTACHMENT | GPU_TEXTURE_USAGE_TEXTURE_BINDING;
1047
+
1048
+ // src/shadow-atlas.ts
1049
+ var SHADOW_ATLAS_DEFAULT_FACE_SIZE = 512;
1050
+ var SHADOW_ATLAS_DEFAULT_LAYERS = 4;
1051
+ var ShadowAtlas = class {
1052
+ /** Backing cube_array depth texture. `null` until `ensure()` has run. */
1053
+ texture = null;
1054
+ /**
1055
+ * Whole-atlas cube_array sampling view used by URP shaders that bind the
1056
+ * atlas at `@group(0) @binding(5)`. `null` until `ensure()` has run.
1057
+ */
1058
+ cubeArrayView = null;
1059
+ /** Comparison sampler for `texture_depth_cube_array`. */
1060
+ compareSampler = null;
1061
+ /** Per-face 2D depth view cache, keyed by `layer * 6 + face`. */
1062
+ faceViews = /* @__PURE__ */ new Map();
1063
+ /** Per-face label cache (debug aid). Reused on re-creation. */
1064
+ device;
1065
+ /** Per-face square size in pixels. */
1066
+ faceSize;
1067
+ /** Cube layer count. */
1068
+ layers;
1069
+ constructor(device, options = {}) {
1070
+ this.device = device;
1071
+ this.faceSize = options.faceSize ?? SHADOW_ATLAS_DEFAULT_FACE_SIZE;
1072
+ this.layers = options.layers ?? SHADOW_ATLAS_DEFAULT_LAYERS;
1073
+ }
1074
+ /**
1075
+ * Returns `true` once the atlas texture is allocated. Used by the extract /
1076
+ * record path to gate "no PointLightShadow → no allocation" (AC-09) — the
1077
+ * caller calls {@link ensure} on a frame that has at least one snapshot;
1078
+ * before that, `isAllocated()` stays `false` and tests can assert no GPU
1079
+ * resources were created.
1080
+ */
1081
+ isAllocated() {
1082
+ return this.texture !== null;
1083
+ }
1084
+ /**
1085
+ * Lazy-allocate the atlas texture + cube_array sampling view + comparison
1086
+ * sampler. Idempotent: subsequent calls are zero-cost no-ops once the
1087
+ * resources exist.
1088
+ *
1089
+ * Throws (via the RHI error registry) on allocation failure. This is the
1090
+ * only path that touches the GPU — keeping it inside one method makes the
1091
+ * "zero-shadow scene = zero allocation" gate easy to enforce: the renderer
1092
+ * never calls this method on a frame with no PointLightShadow entities.
1093
+ */
1094
+ ensure() {
1095
+ if (this.texture !== null) return;
1096
+ const usage = GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING;
1097
+ const texDesc = cubeArrayDepthDescriptor(this.faceSize, this.layers, usage);
1098
+ const texRes = this.device.createTexture(texDesc);
1099
+ if (!texRes.ok) throw texRes.error;
1100
+ this.texture = texRes.value;
1101
+ const viewRes = this.device.createTextureView(this.texture, {
1102
+ label: "shadow-atlas-cube-array-view",
1103
+ dimension: "cube-array",
1104
+ aspect: "depth-only",
1105
+ baseArrayLayer: 0,
1106
+ arrayLayerCount: 6 * this.layers,
1107
+ baseMipLevel: 0,
1108
+ mipLevelCount: 1
1109
+ });
1110
+ if (!viewRes.ok) {
1111
+ this.device.destroyTexture(this.texture);
1112
+ this.texture = null;
1113
+ throw viewRes.error;
1114
+ }
1115
+ this.cubeArrayView = viewRes.value;
1116
+ const sampRes = this.device.createSampler(comparisonSamplerDescriptor());
1117
+ if (!sampRes.ok) {
1118
+ this.device.destroyTexture(this.texture);
1119
+ this.texture = null;
1120
+ this.cubeArrayView = null;
1121
+ throw sampRes.error;
1122
+ }
1123
+ this.compareSampler = sampRes.value;
1124
+ }
1125
+ /**
1126
+ * Whole-atlas cube_array sampling view (`texture_depth_cube_array`). Returns
1127
+ * `null` if the atlas is not yet allocated; the caller should gate on a
1128
+ * non-null pointShadow array before calling {@link ensure} + this getter.
1129
+ */
1130
+ getAtlasView() {
1131
+ return this.cubeArrayView;
1132
+ }
1133
+ /**
1134
+ * Comparison sampler (`compare: 'less'`) for cube_array depth sampling.
1135
+ * Returns `null` if the atlas is not yet allocated.
1136
+ */
1137
+ getComparisonSampler() {
1138
+ return this.compareSampler;
1139
+ }
1140
+ /**
1141
+ * Backing texture handle. Returns `null` if the atlas is not yet allocated.
1142
+ */
1143
+ getTexture() {
1144
+ return this.texture;
1145
+ }
1146
+ /**
1147
+ * Lazy 2D depth view selecting `(layer, face)` (the caller passes
1148
+ * `shadowAtlasLayer` from the snapshot and a face index 0..5). Used as the
1149
+ * depth attachment of the shadow-caster render pass for one cube face.
1150
+ *
1151
+ * Caches per `(layer, face)` so the per-frame shadow loop pays zero
1152
+ * `createTextureView` cost after the first allocation. Cache is cleared on
1153
+ * {@link dispose}.
1154
+ *
1155
+ * @throws PointShadowAtlasUninitializedError if the atlas is not yet
1156
+ * allocated (caller must call {@link ensure} first).
1157
+ * @throws PointShadowAtlasBoundsViolationError if `layer` or `face` is out
1158
+ * of range.
1159
+ * @throws RhiError if the underlying `createTextureView` fails.
1160
+ */
1161
+ faceView(layer, face) {
1162
+ if (this.texture === null) {
1163
+ throw new PointShadowAtlasUninitializedError();
1164
+ }
1165
+ if (layer < 0 || layer >= this.layers) {
1166
+ throw new PointShadowAtlasBoundsViolationError("layer", layer, this.layers);
1167
+ }
1168
+ if (face < 0 || face >= 6) {
1169
+ throw new PointShadowAtlasBoundsViolationError("face", face, 6);
1170
+ }
1171
+ const key = layer * 6 + face;
1172
+ const cached = this.faceViews.get(key);
1173
+ if (cached !== void 0) return cached;
1174
+ const desc = cubeArrayDepthFaceView(layer, face);
1175
+ const r = this.device.createTextureView(this.texture, desc);
1176
+ if (!r.ok) throw r.error;
1177
+ this.faceViews.set(key, r.value);
1178
+ return r.value;
1179
+ }
1180
+ /**
1181
+ * Release the GPU resources and clear the per-face view cache. Idempotent;
1182
+ * subsequent calls are zero-cost. After dispose, `isAllocated()` returns
1183
+ * `false` and the next `ensure()` re-allocates from scratch.
1184
+ */
1185
+ dispose() {
1186
+ this.faceViews.clear();
1187
+ if (this.texture !== null) {
1188
+ this.device.destroyTexture(this.texture);
1189
+ this.texture = null;
1190
+ }
1191
+ this.cubeArrayView = null;
1192
+ this.compareSampler = null;
1193
+ }
1194
+ };
1195
+
820
1196
  // src/render-contract.ts
821
1197
  var STANDARD_OUTPUT_TRANSFORM_FEATURE_ID = "forgeax::standard::output-transform";
1198
+ var FXAA_POST_PROCESS_ID = "forgeax::post::fxaa";
822
1199
  var RENDER_GRAPH_EXECUTION_PHASE_CATALOG = [
823
1200
  "record/graph-execute/point-shadow",
824
1201
  "record/graph-execute/cluster-binner-upload",
@@ -896,6 +1273,6 @@ var RENDER_PHASE_CATALOG = [
896
1273
  ...RENDER_RECORD_PHASE_CATALOG
897
1274
  ];
898
1275
 
899
- export { AtmosphereInvalidParameterError, CLUSTER_GRID_STRIDE_U32, DEFAULT_CLUSTER_GRID, DEFAULT_STANDARD_PROFILE, EnvironmentGenerationFailedError, EnvironmentSourceConflictError, EquirectProjectionFailedError, FogCardinalityError, FrameReceiptStaleError, HdrpDeferredCapsInsufficientError, HdrpIndexListOverflowError, HdrpLightBudgetExceededError, LIGHT_INDEX_LIST_CAPACITY, LifecycleConstructionError, MAX_LIGHTS, MaterialSkinAttrMissingError, ObservationUnavailableError, OwnerStageFailedError, PointShadowAtlasBoundsViolationError, PointShadowAtlasUninitializedError, PointsLinesBudgetExceededError, PointsLinesInvalidStyleError, PointsLinesMaterialUnsupportedError, PointsLinesPrepareFailedError, PointsLinesStyleUnsupportedError, PointsLinesTopologyMismatchError, RENDER_PHASE_CATALOG, RenderFeatureCapabilityMissingError, RenderFeatureDrawRecordingFailedError, RenderFeaturePreparationFailedError, RenderFeaturePreparedStateMismatchError, RenderFeatureRegistrationConflictError, RenderFeatureStageFailedError, RendererContractFailureError, RendererOperationError, SCENE_DATA_TEMPORAL_V1_DESCRIPTOR, SCENE_DATA_TEMPORAL_V1_SCHEMA, STANDARD_LIGHT_COUNTS, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, STANDARD_PIPELINE_ID, STANDARD_POST_STAGE_NAMES, SceneDataUnavailableError, ShadowInvalidConfigError, SkinMaterialMismatchError, SkinPaletteOverflowError, TaaCapsInsufficientError, TransmissionCapabilityMissingError, VertexColorVariantConflictError, VideoUploadUnsupportedError, createSceneDataCatalog, isSceneDataTarget, registerSceneDataTarget, resolveStandardLane, sceneDataError, sceneDataTargetAsAttachment, sceneDataTargetOwner, sceneDataTokenMismatch };
900
- //# sourceMappingURL=chunk-LOSO4CTV.mjs.map
901
- //# sourceMappingURL=chunk-LOSO4CTV.mjs.map
1276
+ export { AtmosphereInvalidParameterError, CLUSTER_GRID_STRIDE_U32, DEFAULT_CLUSTER_GRID, DEFAULT_STANDARD_PROFILE, EnvironmentGenerationFailedError, EnvironmentSourceConflictError, EquirectProjectionFailedError, FXAA_POST_PROCESS_ID, FogCardinalityError, FrameReceiptStaleError, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_COPY_SRC, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_TEXTURE_BINDING, LIGHT_INDEX_LIST_CAPACITY, LifecycleConstructionError, MAX_LIGHTS, MaterialSkinAttrMissingError, ObservationUnavailableError, OwnerStageFailedError, PointShadowAtlasBoundsViolationError, PointShadowAtlasUninitializedError, PointsLinesBudgetExceededError, PointsLinesInvalidStyleError, PointsLinesMaterialUnsupportedError, PointsLinesPrepareFailedError, PointsLinesStyleUnsupportedError, PointsLinesTopologyMismatchError, REFLECTION_PROBE_IBL_STAGES, RENDER_PHASE_CATALOG, RenderFeatureCapabilityMissingError, RenderFeatureDrawRecordingFailedError, RenderFeaturePreparationFailedError, RenderFeaturePreparedStateMismatchError, RenderFeatureRegistrationConflictError, RenderFeatureStageFailedError, RenderIntentInvalidError, RenderTargetCapabilityMissingError, RenderTargetDescriptorInvalidError, RenderTargetOperationFailedError, RenderTargetStateInvalidError, RendererContractFailureError, RendererOperationError, SCENE_DATA_TEMPORAL_V1_DESCRIPTOR, SCENE_DATA_TEMPORAL_V1_SCHEMA, SHADOW_ATLAS_DEFAULT_FACE_SIZE, SHADOW_ATLAS_DEFAULT_LAYERS, STANDARD_LIGHT_COUNTS, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, STANDARD_PIPELINE_ID, STANDARD_POST_STAGE_NAMES, SceneDataUnavailableError, ShadowAtlas, ShadowInvalidConfigError, SkinMaterialMismatchError, SkinPaletteOverflowError, StandardClusterIndexOverflowError, StandardClusterTransportUnavailableError, StandardLightBudgetExceededError, StandardProfileInvalidError, TaaCapsInsufficientError, TemporalFrameSubmitError, TransmissionCapabilityMissingError, VertexColorVariantConflictError, VideoUploadUnsupportedError, VolumeDensityShapeMismatchError, VolumeInvalidBoundsError, VolumeInvalidParametersError, VolumeOwnerConflictError, beginProbeIblUpdate, createIblKernelCache, createProbeIblOutput, createSceneDataCatalog, createStandardClusterLayout, isSceneDataTarget, publishProbeIblOutput, registerSceneDataTarget, resetIblKernelCaches, resolveVolumetricFogProfile, sceneDataError, sceneDataTargetAsAttachment, sceneDataTargetOwner, sceneDataTokenMismatch };
1277
+ //# sourceMappingURL=chunk-6OPXDQ2E.mjs.map
1278
+ //# sourceMappingURL=chunk-6OPXDQ2E.mjs.map