@forgeax/engine-render 0.1.20 → 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 (372) 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 +21 -18
  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-4XINDLAY.mjs → chunk-5YADUCA7.mjs} +1552 -1361
  21. package/dist/chunk-5YADUCA7.mjs.map +1 -0
  22. package/dist/{chunk-TBQJOK2L.mjs → chunk-6OPXDQ2E.mjs} +364 -51
  23. package/dist/chunk-6OPXDQ2E.mjs.map +1 -0
  24. package/dist/{chunk-M2MP4ZOU.mjs → chunk-BXBQQKFQ.mjs} +3 -9
  25. package/dist/chunk-BXBQQKFQ.mjs.map +1 -0
  26. package/dist/{chunk-CDTWTHZR.mjs → chunk-FS2KNUQH.mjs} +548 -6
  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/construct-renderer.mjs +5826 -1003
  42. package/dist/construct-renderer.mjs.map +1 -1
  43. package/dist/environment/frame.d.ts.map +1 -1
  44. package/dist/environment/lifecycle.d.ts +5 -0
  45. package/dist/environment/lifecycle.d.ts.map +1 -1
  46. package/dist/errors/render.d.ts +141 -93
  47. package/dist/errors/render.d.ts.map +1 -1
  48. package/dist/extract/directional-shadow-projection.d.ts +23 -0
  49. package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
  50. package/dist/extract/environment.d.ts +14 -0
  51. package/dist/extract/environment.d.ts.map +1 -1
  52. package/dist/extract/visibility.d.ts.map +1 -1
  53. package/dist/features/fullscreen.d.ts.map +1 -1
  54. package/dist/features/targets.d.ts.map +1 -1
  55. package/dist/features/types.d.ts +10 -0
  56. package/dist/features/types.d.ts.map +1 -1
  57. package/dist/fullscreen-post-process-pass.d.ts +13 -2
  58. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  59. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  60. package/dist/gpu-driven/production-raster.d.ts +0 -1
  61. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  62. package/dist/gpu-scene.d.ts.map +1 -1
  63. package/dist/hdrp-buffers.d.ts +19 -17
  64. package/dist/hdrp-buffers.d.ts.map +1 -1
  65. package/dist/ibl/IblPipelineCache.d.ts +4 -0
  66. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  67. package/dist/ibl/kernel-cache.d.ts +36 -0
  68. package/dist/ibl/kernel-cache.d.ts.map +1 -0
  69. package/dist/index.d.ts +28 -3
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.mjs +4 -4
  72. package/dist/index.mjs.map +1 -1
  73. package/dist/inspection-types.d.ts +51 -0
  74. package/dist/inspection-types.d.ts.map +1 -1
  75. package/dist/instances-derived-bounds.d.ts +50 -0
  76. package/dist/instances-derived-bounds.d.ts.map +1 -0
  77. package/dist/internal.mjs +1 -1
  78. package/dist/light-buffer-layout.d.ts +10 -1
  79. package/dist/light-buffer-layout.d.ts.map +1 -1
  80. package/dist/mesh-material-bindings.d.ts +54 -0
  81. package/dist/mesh-material-bindings.d.ts.map +1 -1
  82. package/dist/pbr-pipeline.d.ts +14 -4
  83. package/dist/pbr-pipeline.d.ts.map +1 -1
  84. package/dist/pipeline/standard-forward-lane.d.ts +2 -1
  85. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  86. package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
  87. package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
  88. package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
  89. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
  90. package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
  91. package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
  92. package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
  93. package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
  94. package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
  95. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
  96. package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
  97. package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
  98. package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
  99. package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
  100. package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
  101. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
  102. package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
  103. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
  104. package/dist/pipeline/standard-pipeline.d.ts +4 -13
  105. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  106. package/dist/pipeline/standard-post.d.ts.map +1 -1
  107. package/dist/pipeline/standard-profile.d.ts +5 -26
  108. package/dist/pipeline/standard-profile.d.ts.map +1 -1
  109. package/dist/pipeline-spec.d.ts +40 -7
  110. package/dist/pipeline-spec.d.ts.map +1 -1
  111. package/dist/point-shadow-inspection.d.ts +21 -0
  112. package/dist/point-shadow-inspection.d.ts.map +1 -0
  113. package/dist/record/frame-lighting.d.ts +27 -32
  114. package/dist/record/frame-lighting.d.ts.map +1 -1
  115. package/dist/record/frame-snapshot.d.ts +28 -14
  116. package/dist/record/frame-snapshot.d.ts.map +1 -1
  117. package/dist/record/frame-targets.d.ts +5 -0
  118. package/dist/record/frame-targets.d.ts.map +1 -1
  119. package/dist/record/frame.d.ts +10 -4
  120. package/dist/record/frame.d.ts.map +1 -1
  121. package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
  122. package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
  123. package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
  124. package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
  125. package/dist/record/gpu-pass-timing/index.d.ts +8 -0
  126. package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
  127. package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
  128. package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
  129. package/dist/record/gpu-pass-timing/session.d.ts +43 -0
  130. package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
  131. package/dist/record/gpu-timing.d.ts +8 -3
  132. package/dist/record/gpu-timing.d.ts.map +1 -1
  133. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  134. package/dist/record/main-pass-material.d.ts +22 -1
  135. package/dist/record/main-pass-material.d.ts.map +1 -1
  136. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  137. package/dist/record/main-pass.d.ts +2 -0
  138. package/dist/record/main-pass.d.ts.map +1 -1
  139. package/dist/record/render-context.d.ts +43 -2
  140. package/dist/record/render-context.d.ts.map +1 -1
  141. package/dist/record/shadow-pass.d.ts.map +1 -1
  142. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  143. package/dist/record/typed-frame-graph.d.ts +72 -4
  144. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  145. package/dist/record/view-ubo.d.ts +7 -4
  146. package/dist/record/view-ubo.d.ts.map +1 -1
  147. package/dist/reflection/filter.d.ts +22 -0
  148. package/dist/reflection/filter.d.ts.map +1 -0
  149. package/dist/reflection/gpu-table.d.ts +25 -0
  150. package/dist/reflection/gpu-table.d.ts.map +1 -0
  151. package/dist/reflection/projection.d.ts +91 -0
  152. package/dist/reflection/projection.d.ts.map +1 -0
  153. package/dist/render-contract.d.ts +49 -7
  154. package/dist/render-contract.d.ts.map +1 -1
  155. package/dist/render-graph-primitives.d.ts +1 -0
  156. package/dist/render-graph-primitives.d.ts.map +1 -1
  157. package/dist/render-pipeline.d.ts +42 -2
  158. package/dist/render-pipeline.d.ts.map +1 -1
  159. package/dist/render-system-extract.d.ts +58 -17
  160. package/dist/render-system-extract.d.ts.map +1 -1
  161. package/dist/render-system.d.ts +17 -2
  162. package/dist/render-system.d.ts.map +1 -1
  163. package/dist/renderer.d.ts +43 -0
  164. package/dist/renderer.d.ts.map +1 -0
  165. package/dist/scene/render-scene.d.ts +14 -0
  166. package/dist/scene/render-scene.d.ts.map +1 -1
  167. package/dist/shadow-atlas.d.ts +3 -3
  168. package/dist/shadow-atlas.d.ts.map +1 -1
  169. package/dist/ssao-buffers.d.ts +3 -0
  170. package/dist/ssao-buffers.d.ts.map +1 -1
  171. package/dist/targets/contracts.d.ts +66 -0
  172. package/dist/targets/contracts.d.ts.map +1 -0
  173. package/dist/targets/graph-projection.d.ts +29 -0
  174. package/dist/targets/graph-projection.d.ts.map +1 -0
  175. package/dist/targets/material-source.d.ts +34 -0
  176. package/dist/targets/material-source.d.ts.map +1 -0
  177. package/dist/targets/owner.d.ts +32 -0
  178. package/dist/targets/owner.d.ts.map +1 -0
  179. package/dist/targets/physical.d.ts +18 -0
  180. package/dist/targets/physical.d.ts.map +1 -0
  181. package/dist/targets/readback.d.ts +39 -0
  182. package/dist/targets/readback.d.ts.map +1 -0
  183. package/dist/temporal/index.mjs +3 -3
  184. package/dist/typed-render-graph-primitives.d.ts +1 -1
  185. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  186. package/dist/typed-shadow-passes.d.ts +1 -1
  187. package/dist/typed-shadow-passes.d.ts.map +1 -1
  188. package/dist/volume/passes.d.ts +2 -2
  189. package/dist/volume/passes.d.ts.map +1 -1
  190. package/package.json +20 -20
  191. package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
  192. package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
  193. package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
  194. package/src/__tests__/cluster-binner.unit.test.ts +35 -0
  195. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -2
  196. package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
  197. package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
  198. package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
  199. package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
  200. package/src/__tests__/cube-camera.integration.test.ts +42 -0
  201. package/src/__tests__/device-feature-admission.unit.test.ts +73 -0
  202. package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -3
  203. package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
  204. package/src/__tests__/factory-contract.integration.test.ts +255 -29
  205. package/src/__tests__/fog-component.unit.test.ts +67 -0
  206. package/src/__tests__/fog.integration.test.ts +86 -0
  207. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
  208. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -9
  209. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +17 -1
  210. package/src/__tests__/gpu-driven-production.integration.test.ts +16 -17
  211. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +12 -4
  212. package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
  213. package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
  214. package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
  215. package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
  216. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
  217. package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
  218. package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
  219. package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
  220. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
  221. package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
  222. package/src/__tests__/instances-culling.integration.test.ts +94 -0
  223. package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
  224. package/src/__tests__/material-observation.integration.test.ts +101 -0
  225. package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
  226. package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
  227. package/src/__tests__/public-surface.test-d.ts +10 -0
  228. package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
  229. package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
  230. package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
  231. package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
  232. package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
  233. package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
  234. package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
  235. package/src/__tests__/render-error-code-owner.test-d.ts +18 -3
  236. package/src/__tests__/render-feature-docs.unit.test.ts +1 -1
  237. package/src/__tests__/render-target-admission.unit.test.ts +80 -0
  238. package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
  239. package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
  240. package/src/__tests__/render-target-material-source.test-d.ts +30 -0
  241. package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
  242. package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
  243. package/src/__tests__/render-target-owner.unit.test.ts +122 -0
  244. package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
  245. package/src/__tests__/render-target-public-schema.json +107 -0
  246. package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
  247. package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
  248. package/src/__tests__/render-target-readback.integration.test.ts +90 -0
  249. package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
  250. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +48 -0
  251. package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
  252. package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
  253. package/src/__tests__/skin-motion-regression.unit.test.ts +132 -0
  254. package/src/__tests__/skinned-shadow-caster.test.ts +11 -2
  255. package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
  256. package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
  257. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +232 -0
  258. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +8 -5
  259. package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
  260. package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
  261. package/src/__tests__/standard-lighting-write.unit.test.ts +377 -0
  262. package/src/__tests__/standard-lighting.integration.test.ts +67 -0
  263. package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
  264. package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
  265. package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
  266. package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -38
  267. package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
  268. package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
  269. package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
  270. package/src/assembly/device-feature-admission.ts +73 -0
  271. package/src/assembly/directional-shadow-inspection.ts +122 -0
  272. package/src/assembly/factory.ts +877 -286
  273. package/src/assembly/host-contract.ts +25 -0
  274. package/src/assembly/render-target-host.ts +847 -0
  275. package/src/assets/asset-decoders.ts +1 -1
  276. package/src/assets/render-asset-port.ts +7 -1
  277. package/src/capture/cube-views.ts +69 -0
  278. package/src/capture/scheduler.ts +265 -0
  279. package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
  280. package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
  281. package/src/components/camera.ts +4 -0
  282. package/src/components/cube-camera.ts +52 -0
  283. package/src/components/directional-light.ts +22 -2
  284. package/src/components/directional-shadow-filter.ts +57 -0
  285. package/src/components/index.ts +2 -0
  286. package/src/components/light-helpers.ts +81 -7
  287. package/src/components/reflection-probe.ts +49 -0
  288. package/src/environment/frame.ts +6 -24
  289. package/src/environment/lifecycle.ts +12 -0
  290. package/src/errors/render.ts +286 -142
  291. package/src/extract/directional-shadow-projection.ts +61 -0
  292. package/src/extract/environment.ts +57 -0
  293. package/src/extract/visibility.ts +25 -1
  294. package/src/features/fullscreen.ts +3 -0
  295. package/src/features/targets.ts +4 -1
  296. package/src/features/types.ts +10 -0
  297. package/src/fullscreen-post-process-pass.ts +43 -2
  298. package/src/gpu-driven/batch-topology.ts +1 -0
  299. package/src/gpu-driven/production-raster.ts +1 -3
  300. package/src/gpu-scene.ts +8 -1
  301. package/src/hdrp-buffers.ts +165 -59
  302. package/src/ibl/IblPipelineCache.ts +11 -0
  303. package/src/ibl/kernel-cache.ts +88 -0
  304. package/src/index.ts +148 -0
  305. package/src/inspection-types.ts +56 -0
  306. package/src/instances-derived-bounds.ts +171 -0
  307. package/src/light-buffer-layout.ts +20 -5
  308. package/src/mesh-material-bindings.ts +132 -0
  309. package/src/pbr-pipeline.ts +106 -17
  310. package/src/pipeline/standard-forward-lane.ts +46 -16
  311. package/src/pipeline/standard-lighting/errors.ts +6 -0
  312. package/src/pipeline/standard-lighting/graph.ts +157 -0
  313. package/src/pipeline/standard-lighting/inspection.ts +88 -0
  314. package/src/pipeline/standard-lighting/layout.ts +31 -0
  315. package/src/pipeline/standard-lighting/light-frame.ts +34 -0
  316. package/src/pipeline/standard-lighting/membership.ts +43 -0
  317. package/src/pipeline/standard-lighting/prepare.ts +37 -0
  318. package/src/pipeline/standard-lighting/topology.ts +120 -0
  319. package/src/pipeline/standard-lighting/transport.ts +77 -0
  320. package/src/pipeline/standard-pipeline.ts +122 -193
  321. package/src/pipeline/standard-post.ts +26 -7
  322. package/src/pipeline/standard-profile.ts +17 -47
  323. package/src/pipeline-spec.ts +84 -21
  324. package/src/point-shadow-inspection.ts +55 -0
  325. package/src/record/__tests__/temporal-payload.unit.test.ts +42 -1
  326. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
  327. package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
  328. package/src/record/frame-lighting.ts +367 -427
  329. package/src/record/frame-snapshot.ts +35 -27
  330. package/src/record/frame-targets.ts +17 -0
  331. package/src/record/frame.ts +261 -74
  332. package/src/record/gpu-pass-timing/contract.ts +180 -0
  333. package/src/record/gpu-pass-timing/errors.ts +34 -0
  334. package/src/record/gpu-pass-timing/index.ts +37 -0
  335. package/src/record/gpu-pass-timing/parser.ts +97 -0
  336. package/src/record/gpu-pass-timing/session.ts +938 -0
  337. package/src/record/gpu-timing.ts +21 -12
  338. package/src/record/main-pass-geometry.ts +120 -80
  339. package/src/record/main-pass-material.ts +95 -9
  340. package/src/record/main-pass-sprite-draws.ts +54 -25
  341. package/src/record/main-pass.ts +71 -15
  342. package/src/record/render-context.ts +72 -0
  343. package/src/record/shadow-pass.ts +17 -28
  344. package/src/record/skybox-post-pass.ts +20 -4
  345. package/src/record/typed-frame-graph.ts +893 -44
  346. package/src/record/view-ubo.ts +63 -28
  347. package/src/reflection/filter.ts +81 -0
  348. package/src/reflection/gpu-table.ts +44 -0
  349. package/src/reflection/projection.ts +281 -0
  350. package/src/render-contract.ts +76 -5
  351. package/src/render-graph-primitives.ts +9 -4
  352. package/src/render-pipeline.ts +117 -2
  353. package/src/render-system-extract.ts +557 -100
  354. package/src/render-system.ts +1095 -66
  355. package/src/renderer.ts +222 -0
  356. package/src/scene/render-scene.ts +115 -9
  357. package/src/shadow-atlas.ts +5 -5
  358. package/src/ssao-buffers.ts +9 -2
  359. package/src/targets/contracts.ts +182 -0
  360. package/src/targets/graph-projection.ts +169 -0
  361. package/src/targets/material-source.ts +143 -0
  362. package/src/targets/owner.ts +214 -0
  363. package/src/targets/physical.ts +18 -0
  364. package/src/targets/readback.ts +153 -0
  365. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
  366. package/src/typed-render-graph-primitives.ts +5 -3
  367. package/src/typed-shadow-passes.ts +46 -40
  368. package/src/volume/passes.ts +15 -9
  369. package/dist/chunk-4XINDLAY.mjs.map +0 -1
  370. package/dist/chunk-CDTWTHZR.mjs.map +0 -1
  371. package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
  372. package/dist/chunk-TBQJOK2L.mjs.map +0 -1
@@ -0,0 +1,88 @@
1
+ import type { StandardTopologyInputValue } from './topology';
2
+ import type { StandardClusterTransport } from './transport';
3
+
4
+ export interface StandardClusterTransportInspection {
5
+ readonly renderPath: 'forward' | 'deferred';
6
+ readonly transport: StandardClusterTransport['kind'];
7
+ readonly producer: StandardClusterTransport['producer'];
8
+ readonly requested: StandardClusterTransport['requestedLightCount'];
9
+ readonly admitted: StandardClusterTransport['admittedLightCount'];
10
+ readonly shadowed: number;
11
+ readonly maxLights: number;
12
+ readonly indexCount: StandardClusterTransport['membershipEntryCount'];
13
+ readonly occupied: StandardClusterTransport['occupiedClusterCount'];
14
+ readonly clusterGridBytes: number;
15
+ readonly lightIndexListBytes: number;
16
+ readonly lightDataBytes: number;
17
+ readonly lightBoundsBytes: number;
18
+ readonly grid: StandardClusterTransport['layout']['grid'];
19
+ }
20
+
21
+ export interface StandardNoLocalLightingInspection {
22
+ readonly renderPath: 'forward' | 'deferred';
23
+ readonly transport: 'not-required';
24
+ readonly producer: 'none';
25
+ readonly requested: 0;
26
+ readonly admitted: 0;
27
+ readonly shadowed: 0;
28
+ readonly maxLights: number;
29
+ readonly indexCount: 0;
30
+ readonly occupied: 0;
31
+ readonly clusterGridBytes: 0;
32
+ readonly lightIndexListBytes: 0;
33
+ readonly lightDataBytes: 0;
34
+ readonly lightBoundsBytes: 0;
35
+ readonly grid: StandardTopologyInputValue['prepared']['layout']['grid'];
36
+ }
37
+
38
+ export type StandardLightingInspection =
39
+ | StandardClusterTransportInspection
40
+ | StandardNoLocalLightingInspection;
41
+
42
+ export function inspectStandardClusterTransport(
43
+ transport: StandardClusterTransport,
44
+ prepared: StandardTopologyInputValue['prepared'],
45
+ ): StandardClusterTransportInspection {
46
+ return Object.freeze({
47
+ renderPath: prepared.renderPath,
48
+ transport: transport.kind,
49
+ producer: transport.producer,
50
+ requested: transport.requestedLightCount,
51
+ admitted: transport.admittedLightCount,
52
+ shadowed: prepared.local.filter((light) => light.shadowed === true).length,
53
+ maxLights: prepared.maxLights,
54
+ indexCount: transport.membershipEntryCount,
55
+ occupied: transport.occupiedClusterCount,
56
+ clusterGridBytes: transport.clusterGridBytes,
57
+ lightIndexListBytes: transport.lightIndexListBytes,
58
+ lightDataBytes: transport.lightDataBytes,
59
+ lightBoundsBytes: transport.lightBoundsBytes,
60
+ // The inspection boundary is JSON-safe and detached from the mutable
61
+ // layout object carried by a per-frame prepared result.
62
+ grid: Object.freeze({ ...transport.layout.grid }),
63
+ });
64
+ }
65
+
66
+ export function inspectStandardLighting(
67
+ input: StandardTopologyInputValue,
68
+ ): StandardLightingInspection {
69
+ if (input.kind === 'no-local-lights') {
70
+ return Object.freeze({
71
+ renderPath: input.prepared.renderPath,
72
+ transport: 'not-required' as const,
73
+ producer: 'none' as const,
74
+ requested: 0 as const,
75
+ admitted: 0 as const,
76
+ shadowed: 0 as const,
77
+ maxLights: input.prepared.maxLights,
78
+ indexCount: 0 as const,
79
+ occupied: 0 as const,
80
+ clusterGridBytes: 0 as const,
81
+ lightIndexListBytes: 0 as const,
82
+ lightDataBytes: 0 as const,
83
+ lightBoundsBytes: 0 as const,
84
+ grid: Object.freeze({ ...input.prepared.layout.grid }),
85
+ });
86
+ }
87
+ return inspectStandardClusterTransport(input.transport, input.prepared);
88
+ }
@@ -0,0 +1,31 @@
1
+ export const DEFAULT_CLUSTER_GRID = { x: 16, y: 9, z: 24 } as const;
2
+ export const CLUSTER_GRID_STRIDE_U32 = 2 as const;
3
+ export const LIGHT_INDEX_LIST_CAPACITY = 1048576 as const;
4
+ export const MAX_LIGHTS = 256 as const;
5
+
6
+ export interface StandardClusterLayout {
7
+ readonly grid: { readonly x: number; readonly y: number; readonly z: number };
8
+ readonly clusterCount: number;
9
+ readonly clusterGridStrideU32: typeof CLUSTER_GRID_STRIDE_U32;
10
+ readonly clusterGridU32Length: number;
11
+ readonly lightIndexListCapacity: typeof LIGHT_INDEX_LIST_CAPACITY;
12
+ readonly lightDataSlotCount: typeof MAX_LIGHTS;
13
+ readonly lightBoundsInt32Length: number;
14
+ }
15
+
16
+ export function createStandardClusterLayout(
17
+ grid: { readonly x: number; readonly y: number; readonly z: number } = DEFAULT_CLUSTER_GRID,
18
+ ): StandardClusterLayout {
19
+ const clusterCount = grid.x * grid.y * grid.z;
20
+ return Object.freeze({
21
+ grid,
22
+ clusterCount,
23
+ clusterGridStrideU32: CLUSTER_GRID_STRIDE_U32,
24
+ clusterGridU32Length: clusterCount * CLUSTER_GRID_STRIDE_U32,
25
+ lightIndexListCapacity: LIGHT_INDEX_LIST_CAPACITY,
26
+ lightDataSlotCount: MAX_LIGHTS,
27
+ lightBoundsInt32Length: MAX_LIGHTS * 6,
28
+ });
29
+ }
30
+
31
+ export const STANDARD_CLUSTER_LAYOUT = createStandardClusterLayout();
@@ -0,0 +1,34 @@
1
+ import type { Mat4, Vec3 } from '@forgeax/engine-math';
2
+ import type {
3
+ DirectionalLightSnapshot,
4
+ PointLightSnapshot,
5
+ SpotLightSnapshot,
6
+ } from '../../render-system-extract';
7
+ import type { StandardLightCount } from '../standard-profile';
8
+
9
+ export interface StandardLocalLightInput {
10
+ readonly kind: 'point' | 'spot';
11
+ readonly position: Vec3;
12
+ readonly range: number;
13
+ /** Whether the shadow producer admitted this local light to its atlas. */
14
+ readonly shadowed: boolean;
15
+ /**
16
+ * The immutable extract snapshot used by the record payload packer. Keeping
17
+ * it on the POD frame prevents Forward/Deferred from rebuilding a second
18
+ * light list while leaving hand-authored unit fixtures source-free.
19
+ */
20
+ readonly source?: PointLightSnapshot | SpotLightSnapshot;
21
+ }
22
+
23
+ export interface StandardLightFrame {
24
+ readonly directional: DirectionalLightSnapshot | undefined;
25
+ readonly local: readonly StandardLocalLightInput[];
26
+ readonly view: Mat4;
27
+ readonly projection: Mat4;
28
+ readonly near: number;
29
+ readonly far: number;
30
+ readonly grid: { readonly x: number; readonly y: number; readonly z: number };
31
+ readonly lightCount: StandardLightCount;
32
+ /** Graph path carried into inspection from the active Standard profile. */
33
+ readonly renderPath: 'forward' | 'deferred';
34
+ }
@@ -0,0 +1,43 @@
1
+ import { err, ok, type Result } from '@forgeax/engine-types';
2
+ import { bin, type ClusterBinScratch, createClusterBinScratch } from '../../cluster-binner';
3
+ import type { RenderError } from '../../errors/render';
4
+ import { fromClusterBinError } from './errors';
5
+ import type { StandardClusterLayout } from './layout';
6
+ import type { StandardLightFrame } from './light-frame';
7
+
8
+ export interface StandardClusterMembership {
9
+ readonly clusterGrid: Uint32Array;
10
+ readonly lightIndexList: Uint32Array;
11
+ readonly lightBounds: Int32Array;
12
+ readonly membershipEntryCount: number;
13
+ readonly scratch: ClusterBinScratch;
14
+ }
15
+
16
+ export function deriveStandardMembership(
17
+ frame: StandardLightFrame,
18
+ layout: StandardClusterLayout,
19
+ scratch = createClusterBinScratch(),
20
+ ): Result<StandardClusterMembership, RenderError> {
21
+ const clusterGrid = new Uint32Array(layout.clusterGridU32Length);
22
+ const lightIndexList = new Uint32Array(layout.lightIndexListCapacity);
23
+ const result = bin(
24
+ frame.local,
25
+ frame.view,
26
+ frame.projection,
27
+ layout.grid,
28
+ frame.near,
29
+ frame.far,
30
+ clusterGrid,
31
+ lightIndexList,
32
+ layout.lightIndexListCapacity,
33
+ scratch,
34
+ );
35
+ if (!result.ok) return err(fromClusterBinError(result.error));
36
+ return ok({
37
+ clusterGrid,
38
+ lightIndexList,
39
+ lightBounds: scratch.lightBounds.slice(0, frame.local.length * 6),
40
+ membershipEntryCount: result.value,
41
+ scratch,
42
+ });
43
+ }
@@ -0,0 +1,37 @@
1
+ import { err, ok, type Result } from '@forgeax/engine-types';
2
+ import { type RenderError, StandardLightBudgetExceededError } from '../../errors/render';
3
+ import { MAX_LIGHTS } from '../standard-profile';
4
+ import { createStandardClusterLayout, type StandardClusterLayout } from './layout';
5
+ import type { StandardLightFrame } from './light-frame';
6
+ import { deriveStandardMembership, type StandardClusterMembership } from './membership';
7
+
8
+ export type { StandardLightFrame } from './light-frame';
9
+
10
+ export interface PreparedStandardLighting extends StandardClusterMembership {
11
+ readonly directional: StandardLightFrame['directional'];
12
+ readonly local: StandardLightFrame['local'];
13
+ readonly layout: StandardClusterLayout;
14
+ readonly membershipLightCount: number;
15
+ readonly renderPath: NonNullable<StandardLightFrame['renderPath']>;
16
+ readonly maxLights: StandardLightFrame['lightCount'];
17
+ }
18
+
19
+ export function prepareStandardLighting(
20
+ frame: StandardLightFrame,
21
+ ): Result<PreparedStandardLighting, RenderError> {
22
+ if (frame.local.length > frame.lightCount || frame.local.length > MAX_LIGHTS) {
23
+ return err(new StandardLightBudgetExceededError(frame.local.length, frame.lightCount));
24
+ }
25
+ const layout = createStandardClusterLayout(frame.grid);
26
+ const membership = deriveStandardMembership(frame, layout);
27
+ if (!membership.ok) return membership;
28
+ return ok({
29
+ ...membership.value,
30
+ directional: frame.directional,
31
+ local: frame.local,
32
+ layout,
33
+ membershipLightCount: frame.local.length,
34
+ renderPath: frame.renderPath,
35
+ maxLights: frame.lightCount,
36
+ });
37
+ }
@@ -0,0 +1,120 @@
1
+ import { err, ok, type Result } from '@forgeax/engine-types';
2
+ import type { PreparedStandardLighting } from './prepare';
3
+ import type { StandardClusterTransport } from './transport';
4
+
5
+ /** A prepared frame with no local lights on a non-storage direct backend. */
6
+ export interface StandardNoLocalTopologyInput {
7
+ readonly kind: 'no-local-lights';
8
+ readonly prepared: PreparedStandardLighting;
9
+ }
10
+
11
+ /** A prepared frame whose Standard surface uses one proven Cluster transport. */
12
+ export interface StandardClusteredTopologyInput {
13
+ readonly kind: 'clustered';
14
+ readonly prepared: PreparedStandardLighting;
15
+ readonly transport: StandardClusterTransport;
16
+ }
17
+
18
+ /**
19
+ * The only lighting value accepted by a Standard topology adapter. It is a
20
+ * projection of one prepared frame, not a second light/config/capability
21
+ * input. Both Forward and Deferred keep the same object identity for a frame.
22
+ */
23
+ export type StandardTopologyInput = StandardNoLocalTopologyInput | StandardClusteredTopologyInput;
24
+
25
+ export type StandardTopologyInputValue = StandardTopologyInput;
26
+
27
+ /**
28
+ * Stable identity for the graph-facing Standard lighting declaration.
29
+ *
30
+ * The prepared light payload itself is frame-local and must never be retained
31
+ * by a compiled graph. These are the only facts that affect the Cluster graph
32
+ * shape and persistent buffer contract, so the record owner can reject an old
33
+ * graph before uploading a payload derived from a different declaration.
34
+ */
35
+ export function standardLightingTopologySignature(
36
+ input: StandardTopologyInputValue | undefined,
37
+ ): string {
38
+ if (input === undefined) return 'missing';
39
+ if (input.kind === 'no-local-lights') return 'no-local-lights';
40
+ return JSON.stringify({
41
+ kind: input.kind,
42
+ transport: input.transport.kind,
43
+ producer: input.transport.producer,
44
+ grid: input.prepared.layout.grid,
45
+ clusterGridU32Length: input.prepared.layout.clusterGridU32Length,
46
+ lightIndexListCapacity: input.prepared.layout.lightIndexListCapacity,
47
+ lightDataSlotCount: input.prepared.layout.lightDataSlotCount,
48
+ lightBoundsInt32Length: input.prepared.layout.lightBoundsInt32Length,
49
+ });
50
+ }
51
+
52
+ export interface StandardTopologyInputError {
53
+ readonly code: 'topology-input-invalid';
54
+ readonly expected: 'prepared Standard lighting topology input';
55
+ readonly hint: 'derive topology from prepared Standard lighting';
56
+ readonly detail: {
57
+ readonly field: 'kind' | 'prepared' | 'transport' | 'lights' | 'capabilities';
58
+ };
59
+ }
60
+
61
+ function invalid(
62
+ field: StandardTopologyInputError['detail']['field'],
63
+ ): Result<never, StandardTopologyInputError> {
64
+ return err({
65
+ code: 'topology-input-invalid',
66
+ expected: 'prepared Standard lighting topology input',
67
+ hint: 'derive topology from prepared Standard lighting',
68
+ detail: { field },
69
+ });
70
+ }
71
+
72
+ /**
73
+ * Validate that transport and prepared membership are the same derivation.
74
+ * The identity checks make it impossible for an adapter to silently combine
75
+ * one path's layout/counts with another path's prepared light corpus.
76
+ */
77
+ export function deriveStandardTopologyInput(
78
+ input: StandardTopologyInput,
79
+ ): Result<StandardTopologyInputValue, StandardTopologyInputError> {
80
+ const candidate = input as StandardTopologyInput & {
81
+ readonly kind?: unknown;
82
+ readonly lights?: unknown;
83
+ readonly capabilities?: unknown;
84
+ readonly transport?: unknown;
85
+ };
86
+ if ('lights' in candidate) return invalid('lights');
87
+ if ('capabilities' in candidate) return invalid('capabilities');
88
+ if (input === null || typeof input !== 'object') return invalid('kind');
89
+ if (input.prepared === null || typeof input.prepared !== 'object') {
90
+ return invalid('prepared');
91
+ }
92
+
93
+ const prepared = input.prepared;
94
+ if (input.kind === 'no-local-lights') {
95
+ if (prepared.local.length !== 0 || 'transport' in candidate) return invalid('transport');
96
+ return ok(input);
97
+ }
98
+ if (input.kind !== 'clustered') return invalid('kind');
99
+ if (
100
+ !('transport' in candidate) ||
101
+ candidate.transport === null ||
102
+ typeof candidate.transport !== 'object'
103
+ ) {
104
+ return invalid('transport');
105
+ }
106
+
107
+ const transport = input.transport;
108
+ const requested = prepared.local.length;
109
+ const transportMatchesPrepared =
110
+ transport.layout === prepared.layout &&
111
+ transport.requestedLightCount === requested &&
112
+ transport.admittedLightCount === requested &&
113
+ transport.membershipEntryCount === prepared.membershipEntryCount &&
114
+ transport.lightBoundsBytes === prepared.lightBounds.byteLength;
115
+ const producerMatchesKind =
116
+ (transport.producer === 'gpu' && transport.kind === 'compute-storage') ||
117
+ (transport.producer === 'cpu' && transport.kind === 'cpu-storage');
118
+ if (!transportMatchesPrepared || !producerMatchesKind) return invalid('transport');
119
+ return ok(input);
120
+ }
@@ -0,0 +1,77 @@
1
+ import { err, ok, type Result } from '@forgeax/engine-types';
2
+ import { type RenderError, StandardClusterTransportUnavailableError } from '../../errors/render';
3
+ import type { PreparedStandardLighting } from './prepare';
4
+
5
+ export interface StandardClusterCapabilities {
6
+ readonly compute: boolean;
7
+ readonly storageBuffer: boolean;
8
+ /**
9
+ * The graph producer is ready to encode the selected compute lane. The
10
+ * renderer supplies this from the actual pipeline + bind-group layout; it is
11
+ * required so capability admission cannot forge a GPU producer from
12
+ * `compute` alone.
13
+ */
14
+ readonly membershipPipelineReady: boolean;
15
+ }
16
+
17
+ /** Only transports with storage-backed membership representation exist. */
18
+ export type StandardClusterTransportKind = 'compute-storage' | 'cpu-storage';
19
+ export type StandardClusterMembershipProducer = 'cpu' | 'gpu';
20
+
21
+ export interface StandardClusterTransport {
22
+ readonly kind: StandardClusterTransportKind;
23
+ readonly producer: StandardClusterMembershipProducer;
24
+ readonly layout: PreparedStandardLighting['layout'];
25
+ readonly requestedLightCount: number;
26
+ readonly admittedLightCount: number;
27
+ readonly membershipEntryCount: number;
28
+ readonly occupiedClusterCount: number;
29
+ readonly clusterGridBytes: number;
30
+ readonly lightIndexListBytes: number;
31
+ readonly lightDataBytes: number;
32
+ readonly lightBoundsBytes: number;
33
+ }
34
+
35
+ function occupiedClusterCount(prepared: PreparedStandardLighting): number {
36
+ let occupied = 0;
37
+ for (let index = 1; index < prepared.clusterGrid.length; index += 2) {
38
+ if ((prepared.clusterGrid[index] ?? 0) > 0) occupied += 1;
39
+ }
40
+ return occupied;
41
+ }
42
+
43
+ /**
44
+ * Select a transport from one prepared frame. Capability facts choose only a
45
+ * producer/storage pair; all counts and byte sizes come from that frame.
46
+ */
47
+ export function selectStandardClusterTransport(
48
+ capabilities: StandardClusterCapabilities,
49
+ prepared: PreparedStandardLighting,
50
+ ): Result<StandardClusterTransport, RenderError> {
51
+ const requested = prepared.local.length;
52
+ if (!capabilities.storageBuffer) {
53
+ return err(
54
+ new StandardClusterTransportUnavailableError(
55
+ requested,
56
+ 'enable a proven storage-buffer Cluster transport; compute without storage is not a membership path',
57
+ ),
58
+ );
59
+ }
60
+
61
+ const producer: StandardClusterMembershipProducer =
62
+ capabilities.compute && capabilities.membershipPipelineReady ? 'gpu' : 'cpu';
63
+ const kind: StandardClusterTransportKind = producer === 'gpu' ? 'compute-storage' : 'cpu-storage';
64
+ return ok({
65
+ kind,
66
+ producer,
67
+ layout: prepared.layout,
68
+ requestedLightCount: requested,
69
+ admittedLightCount: requested,
70
+ membershipEntryCount: prepared.membershipEntryCount,
71
+ occupiedClusterCount: occupiedClusterCount(prepared),
72
+ clusterGridBytes: prepared.layout.clusterGridU32Length * Uint32Array.BYTES_PER_ELEMENT,
73
+ lightIndexListBytes: prepared.membershipEntryCount * Uint32Array.BYTES_PER_ELEMENT,
74
+ lightDataBytes: requested * 64,
75
+ lightBoundsBytes: prepared.lightBounds.byteLength,
76
+ });
77
+ }