@forgeax/engine-render 0.1.33 → 0.1.34

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 (518) hide show
  1. package/README.md +1010 -124
  2. package/dist/assembly/backend-contract.d.ts +2 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  5. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  6. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  7. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  8. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  9. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  10. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  11. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  12. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  14. package/dist/assembly/factory.d.ts +1 -1
  15. package/dist/assembly/factory.d.ts.map +1 -1
  16. package/dist/assembly/host-contract.d.ts +3 -3
  17. package/dist/assembly/host-contract.d.ts.map +1 -1
  18. package/dist/assembly/material/assembly.d.ts.map +1 -1
  19. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  20. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  21. package/dist/assembly/material-shader-policy.d.ts +16 -2
  22. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  23. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  24. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  25. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  26. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  27. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  28. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  29. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  30. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  31. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  32. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  33. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  34. package/dist/assembly/renderer-inspection.d.ts +11 -0
  35. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  36. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  37. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  38. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  39. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  40. package/dist/assembly/webgpu-ready.d.ts +1 -1
  41. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  42. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  43. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  44. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  45. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  46. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  47. package/dist/authoring.mjs +1 -1
  48. package/dist/barrel-distortion.d.ts +47 -0
  49. package/dist/barrel-distortion.d.ts.map +1 -0
  50. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  51. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  52. package/dist/{chunk-ZDQWGQW7.mjs → chunk-HEB564WF.mjs} +4 -4
  53. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-HEB564WF.mjs.map} +1 -1
  54. package/dist/{chunk-VOZWDM3L.mjs → chunk-MKDIT2EM.mjs} +1307 -188
  55. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  56. package/dist/{chunk-LEAXOMYJ.mjs → chunk-OCDLEI6I.mjs} +3 -3
  57. package/dist/{chunk-LEAXOMYJ.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  58. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  59. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  60. package/dist/{chunk-3RTCJTH4.mjs → chunk-SHFUFJ5N.mjs} +184 -13
  61. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  62. package/dist/{chunk-OO3DRYK7.mjs → chunk-UI5SFODX.mjs} +176 -96
  63. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  64. package/dist/{chunk-PLAXOOX5.mjs → chunk-UINHLCZA.mjs} +561 -79
  65. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  66. package/dist/{chunk-NB2S7ZRX.mjs → chunk-WEX45HKH.mjs} +127 -386
  67. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  68. package/dist/cloud/density.d.ts +55 -0
  69. package/dist/cloud/density.d.ts.map +1 -0
  70. package/dist/cloud/extract.d.ts +25 -0
  71. package/dist/cloud/extract.d.ts.map +1 -0
  72. package/dist/cloud/feature.d.ts +57 -0
  73. package/dist/cloud/feature.d.ts.map +1 -0
  74. package/dist/cloud/frame-context.d.ts +8 -0
  75. package/dist/cloud/frame-context.d.ts.map +1 -0
  76. package/dist/cloud/inspection.d.ts +59 -0
  77. package/dist/cloud/inspection.d.ts.map +1 -0
  78. package/dist/cloud/optics.d.ts +56 -0
  79. package/dist/cloud/optics.d.ts.map +1 -0
  80. package/dist/cloud/parameters.d.ts +73 -0
  81. package/dist/cloud/parameters.d.ts.map +1 -0
  82. package/dist/cloud/resources.d.ts +60 -0
  83. package/dist/cloud/resources.d.ts.map +1 -0
  84. package/dist/cloud/shadow.d.ts +42 -0
  85. package/dist/cloud/shadow.d.ts.map +1 -0
  86. package/dist/cloud/temporal.d.ts +74 -0
  87. package/dist/cloud/temporal.d.ts.map +1 -0
  88. package/dist/components/barrel-distortion.d.ts +13 -0
  89. package/dist/components/barrel-distortion.d.ts.map +1 -0
  90. package/dist/components/cloud-layer.d.ts +29 -0
  91. package/dist/components/cloud-layer.d.ts.map +1 -0
  92. package/dist/components/index.d.ts +2 -0
  93. package/dist/components/index.d.ts.map +1 -1
  94. package/dist/components/instances.d.ts +20 -6
  95. package/dist/components/instances.d.ts.map +1 -1
  96. package/dist/construct-renderer.d.ts +1 -1
  97. package/dist/construct-renderer.d.ts.map +1 -1
  98. package/dist/construct-renderer.mjs +6759 -2875
  99. package/dist/construct-renderer.mjs.map +1 -1
  100. package/dist/dynamic-geometry.d.ts +5 -1
  101. package/dist/dynamic-geometry.d.ts.map +1 -1
  102. package/dist/errors/cloud.d.ts +59 -0
  103. package/dist/errors/cloud.d.ts.map +1 -0
  104. package/dist/errors/render.d.ts +18 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  107. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  108. package/dist/extract/camera.d.ts.map +1 -1
  109. package/dist/extract/contracts.d.ts +5 -1
  110. package/dist/extract/contracts.d.ts.map +1 -1
  111. package/dist/features/barrel-distortion.d.ts +29 -0
  112. package/dist/features/barrel-distortion.d.ts.map +1 -0
  113. package/dist/features/error-reporting.d.ts +6 -2
  114. package/dist/features/error-reporting.d.ts.map +1 -1
  115. package/dist/features/host.d.ts +10 -0
  116. package/dist/features/host.d.ts.map +1 -1
  117. package/dist/features/plan.d.ts +8 -0
  118. package/dist/features/plan.d.ts.map +1 -1
  119. package/dist/features/render-graph-contribution.d.ts +5 -0
  120. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  121. package/dist/features/render-graph-raster.d.ts +1 -0
  122. package/dist/features/render-graph-raster.d.ts.map +1 -1
  123. package/dist/features/targets.d.ts +2 -0
  124. package/dist/features/targets.d.ts.map +1 -1
  125. package/dist/features/types.d.ts +44 -0
  126. package/dist/features/types.d.ts.map +1 -1
  127. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  128. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  129. package/dist/gpu-dirty-ranges.d.ts +11 -0
  130. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  131. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  132. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  133. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  134. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  135. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  136. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  137. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  138. package/dist/gpu-driven/production-raster.d.ts +47 -3
  139. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  140. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  141. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  142. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  143. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  144. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  145. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  146. package/dist/gpu-scene.d.ts +5 -0
  147. package/dist/gpu-scene.d.ts.map +1 -1
  148. package/dist/hdrp-buffers.d.ts +2 -2
  149. package/dist/hdrp-buffers.d.ts.map +1 -1
  150. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +27 -7
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +258 -8
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +135 -1
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instance-buffer-cache.d.ts +4 -4
  159. package/dist/instance-buffer-cache.d.ts.map +1 -1
  160. package/dist/instances.d.ts +48 -100
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.mjs +7 -7
  163. package/dist/pbr-pipeline.d.ts +19 -1
  164. package/dist/pbr-pipeline.d.ts.map +1 -1
  165. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  166. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  167. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  168. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  169. package/dist/pipeline/standard-output/types.d.ts +4 -2
  170. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  171. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  172. package/dist/pipeline/standard-post.d.ts.map +1 -1
  173. package/dist/pipeline-builder.d.ts +1 -1
  174. package/dist/pipeline-builder.d.ts.map +1 -1
  175. package/dist/plugin.d.ts.map +1 -1
  176. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  177. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  178. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  179. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  180. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  181. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  182. package/dist/record/fold-buckets.d.ts +95 -0
  183. package/dist/record/fold-buckets.d.ts.map +1 -0
  184. package/dist/record/fold-instance-buffer.d.ts +6 -0
  185. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  186. package/dist/record/frame-lighting.d.ts +1 -0
  187. package/dist/record/frame-lighting.d.ts.map +1 -1
  188. package/dist/record/frame-snapshot.d.ts +37 -3
  189. package/dist/record/frame-snapshot.d.ts.map +1 -1
  190. package/dist/record/frame.d.ts +10 -61
  191. package/dist/record/frame.d.ts.map +1 -1
  192. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  193. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  194. package/dist/record/gpu-timing.d.ts +8 -0
  195. package/dist/record/gpu-timing.d.ts.map +1 -1
  196. package/dist/record/main-pass-geometry.d.ts +21 -5
  197. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  198. package/dist/record/main-pass-material.d.ts +7 -1
  199. package/dist/record/main-pass-material.d.ts.map +1 -1
  200. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  201. package/dist/record/main-pass.d.ts +13 -2
  202. package/dist/record/main-pass.d.ts.map +1 -1
  203. package/dist/record/motion-blur-receipt.d.ts +11 -0
  204. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  205. package/dist/record/probe-blend-buffer.d.ts +16 -0
  206. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  207. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  208. package/dist/record/render-context.d.ts +22 -3
  209. package/dist/record/render-context.d.ts.map +1 -1
  210. package/dist/record/shadow-pass.d.ts +2 -0
  211. package/dist/record/shadow-pass.d.ts.map +1 -1
  212. package/dist/record/skybox-post-pass.d.ts +1 -1
  213. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  214. package/dist/record/typed-frame-graph.d.ts +22 -2
  215. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  216. package/dist/record/view-ubo.d.ts +11 -3
  217. package/dist/record/view-ubo.d.ts.map +1 -1
  218. package/dist/record/volume-params.d.ts +9 -0
  219. package/dist/record/volume-params.d.ts.map +1 -0
  220. package/dist/recovery/render-system-candidate.d.ts +10 -0
  221. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  222. package/dist/reflection/record-owner.d.ts.map +1 -1
  223. package/dist/render-contract.d.ts +42 -4
  224. package/dist/render-contract.d.ts.map +1 -1
  225. package/dist/render-graph-primitives.d.ts.map +1 -1
  226. package/dist/render-pipeline.d.ts +103 -2
  227. package/dist/render-pipeline.d.ts.map +1 -1
  228. package/dist/render-system-extract-tail.d.ts +3 -2
  229. package/dist/render-system-extract-tail.d.ts.map +1 -1
  230. package/dist/render-system-extract.d.ts +16 -9
  231. package/dist/render-system-extract.d.ts.map +1 -1
  232. package/dist/render-system-presentation.d.ts +23 -0
  233. package/dist/render-system-presentation.d.ts.map +1 -0
  234. package/dist/render-system-producer-roots.d.ts +10 -0
  235. package/dist/render-system-producer-roots.d.ts.map +1 -0
  236. package/dist/render-system-residency.d.ts +12 -0
  237. package/dist/render-system-residency.d.ts.map +1 -0
  238. package/dist/render-system.d.ts +19 -14
  239. package/dist/render-system.d.ts.map +1 -1
  240. package/dist/scene/probe-blend.d.ts +27 -0
  241. package/dist/scene/probe-blend.d.ts.map +1 -1
  242. package/dist/scene/render-scene.d.ts +12 -5
  243. package/dist/scene/render-scene.d.ts.map +1 -1
  244. package/dist/ssao-buffers.d.ts +9 -0
  245. package/dist/ssao-buffers.d.ts.map +1 -1
  246. package/dist/surface/dynamic-input.d.ts +133 -0
  247. package/dist/surface/dynamic-input.d.ts.map +1 -0
  248. package/dist/surface/gpu-driven.d.ts +41 -0
  249. package/dist/surface/gpu-driven.d.ts.map +1 -0
  250. package/dist/surface/submission-observation.d.ts +136 -0
  251. package/dist/surface/submission-observation.d.ts.map +1 -0
  252. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  253. package/dist/temporal/gpu.d.ts +13 -1
  254. package/dist/temporal/gpu.d.ts.map +1 -1
  255. package/dist/temporal/index.mjs +5 -5
  256. package/dist/temporal/inspection.d.ts.map +1 -1
  257. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  258. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  259. package/dist/transmission/single-layer-medium.d.ts +89 -0
  260. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  261. package/dist/typed-render-graph-primitives.d.ts +14 -2
  262. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  263. package/dist/volume/component.d.ts +9 -4
  264. package/dist/volume/component.d.ts.map +1 -1
  265. package/dist/volume/extract.d.ts +1 -1
  266. package/dist/volume/extract.d.ts.map +1 -1
  267. package/dist/volume/inspection.d.ts +2 -0
  268. package/dist/volume/inspection.d.ts.map +1 -1
  269. package/dist/volume/passes.d.ts +4 -1
  270. package/dist/volume/passes.d.ts.map +1 -1
  271. package/dist/volume/resources.d.ts.map +1 -1
  272. package/package.json +22 -21
  273. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  274. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  275. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  276. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  277. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  278. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  279. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  280. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  281. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  282. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  283. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  284. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  285. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  286. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  287. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  288. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  289. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  290. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  291. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  292. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  293. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  294. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  295. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  296. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  297. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  298. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  299. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  300. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  301. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  302. package/src/__tests__/instances-store.unit.test.ts +97 -305
  303. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  304. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  305. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  306. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  307. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  308. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  309. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  310. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  311. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  312. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  313. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  314. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  315. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  316. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  317. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  318. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  319. package/src/__tests__/render-error-code-owner.test-d.ts +7 -0
  320. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  321. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  322. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  323. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  324. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  325. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  326. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  327. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  328. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  329. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  330. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  331. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  332. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  333. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  334. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  335. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  336. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  337. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  338. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  339. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  340. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  341. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  342. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  343. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  344. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  345. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  346. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  347. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  348. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  349. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  350. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  351. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  352. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  353. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  354. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  355. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  356. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  357. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  358. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  359. package/src/assembly/backend-contract.ts +30 -0
  360. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  361. package/src/assembly/canvas-draw-guard.ts +11 -0
  362. package/src/assembly/cloud-shadow-entry.ts +22 -0
  363. package/src/assembly/dynamic-geometry-host.ts +65 -37
  364. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  365. package/src/assembly/factory.ts +2 -30
  366. package/src/assembly/host-contract.ts +3 -3
  367. package/src/assembly/material/assembly.ts +25 -13
  368. package/src/assembly/material/pipeline-helpers.ts +53 -12
  369. package/src/assembly/material-shader-policy.ts +55 -0
  370. package/src/assembly/material-shader-prewarm.ts +21 -10
  371. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  372. package/src/assembly/recovery/renderer-recover.ts +41 -18
  373. package/src/assembly/render-feature-post-processes.ts +54 -0
  374. package/src/assembly/renderer-facade.ts +4 -1
  375. package/src/assembly/renderer-feature-inspection.ts +8 -2
  376. package/src/assembly/renderer-frame-transaction.ts +23 -0
  377. package/src/assembly/renderer-inspection.ts +28 -0
  378. package/src/assembly/skin-palette-owner.ts +1 -1
  379. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  380. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  381. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  382. package/src/assembly/webgpu-ready.ts +115 -61
  383. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  384. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  385. package/src/assembly/webgpu-renderer.ts +214 -252
  386. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  387. package/src/barrel-distortion.ts +247 -0
  388. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  389. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  390. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  391. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  392. package/src/cloud/density.ts +600 -0
  393. package/src/cloud/extract.ts +110 -0
  394. package/src/cloud/feature.ts +1810 -0
  395. package/src/cloud/frame-context.ts +42 -0
  396. package/src/cloud/inspection.ts +130 -0
  397. package/src/cloud/optics.ts +285 -0
  398. package/src/cloud/parameters.ts +255 -0
  399. package/src/cloud/resources.ts +122 -0
  400. package/src/cloud/shadow.ts +167 -0
  401. package/src/cloud/temporal.ts +226 -0
  402. package/src/components/barrel-distortion.ts +46 -0
  403. package/src/components/cloud-layer.ts +47 -0
  404. package/src/components/index.ts +2 -0
  405. package/src/components/instances.ts +18 -45
  406. package/src/components/sprite-instances.ts +1 -1
  407. package/src/construct-renderer.ts +1 -1
  408. package/src/dynamic-geometry.ts +12 -1
  409. package/src/errors/cloud.ts +103 -0
  410. package/src/errors/render.ts +44 -7
  411. package/src/examples/single-layer-medium-surface.ts +59 -0
  412. package/src/extract/camera.ts +15 -1
  413. package/src/extract/contracts.ts +5 -0
  414. package/src/features/barrel-distortion.ts +172 -0
  415. package/src/features/error-reporting.ts +26 -6
  416. package/src/features/host.ts +115 -14
  417. package/src/features/plan.ts +8 -0
  418. package/src/features/render-graph-contribution.ts +9 -0
  419. package/src/features/render-graph-raster.ts +45 -3
  420. package/src/features/targets.ts +66 -0
  421. package/src/features/types.ts +47 -0
  422. package/src/fullscreen-post-process-pass.ts +41 -9
  423. package/src/gpu-dirty-ranges.ts +48 -0
  424. package/src/gpu-driven/batch-topology.ts +53 -0
  425. package/src/gpu-driven/material-artifacts.ts +33 -25
  426. package/src/gpu-driven/prepared-draw.ts +12 -4
  427. package/src/gpu-driven/production-raster-material.ts +1894 -0
  428. package/src/gpu-driven/production-raster.ts +825 -784
  429. package/src/gpu-driven/resource-allocation.ts +142 -0
  430. package/src/gpu-driven/shadow-ownership.ts +71 -0
  431. package/src/gpu-driven/view-gpu.ts +164 -10
  432. package/src/gpu-scene.ts +75 -84
  433. package/src/hdrp-buffers.ts +4 -3
  434. package/src/ibl/skylight-bind-group.ts +49 -7
  435. package/src/index.ts +196 -9
  436. package/src/inspection-types.ts +162 -0
  437. package/src/instance-buffer-cache.ts +4 -4
  438. package/src/instances.ts +149 -569
  439. package/src/pbr-pipeline.ts +219 -13
  440. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  441. package/src/pipeline/standard-forward-lane.ts +313 -57
  442. package/src/pipeline/standard-output/graph.ts +8 -2
  443. package/src/pipeline/standard-output/types.ts +12 -1
  444. package/src/pipeline/standard-pipeline.ts +291 -18
  445. package/src/pipeline/standard-post.ts +90 -24
  446. package/src/pipeline-builder.ts +1 -1
  447. package/src/plugin.ts +4 -0
  448. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  449. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  450. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  451. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  452. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  453. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  454. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  455. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  456. package/src/record/barrel-distortion-frame.ts +110 -0
  457. package/src/record/dynamic-geometry-consumption.ts +39 -9
  458. package/src/record/fold-buckets.ts +852 -0
  459. package/src/record/fold-instance-buffer.ts +51 -0
  460. package/src/record/frame-lighting.ts +36 -2
  461. package/src/record/frame-snapshot.ts +39 -3
  462. package/src/record/frame.ts +217 -1084
  463. package/src/record/gpu-draw-receipts.ts +38 -0
  464. package/src/record/gpu-timing.ts +48 -5
  465. package/src/record/main-pass-geometry.ts +251 -82
  466. package/src/record/main-pass-material.ts +66 -4
  467. package/src/record/main-pass-sprite-draws.ts +7 -65
  468. package/src/record/main-pass.ts +156 -20
  469. package/src/record/motion-blur-receipt.ts +91 -0
  470. package/src/record/probe-blend-buffer.ts +180 -0
  471. package/src/record/recovery-pipeline.ts +35 -3
  472. package/src/record/render-context.ts +39 -3
  473. package/src/record/shadow-pass.ts +30 -1
  474. package/src/record/skybox-post-pass.ts +28 -4
  475. package/src/record/typed-frame-graph.ts +770 -134
  476. package/src/record/view-ubo.ts +26 -3
  477. package/src/record/volume-params.ts +225 -0
  478. package/src/recovery/render-system-candidate.ts +235 -42
  479. package/src/reflection/record-owner.ts +7 -3
  480. package/src/render-contract.ts +48 -4
  481. package/src/render-graph-primitives.ts +7 -1
  482. package/src/render-pipeline.ts +130 -0
  483. package/src/render-system-extract-tail.ts +57 -61
  484. package/src/render-system-extract.ts +74 -76
  485. package/src/render-system-presentation.ts +56 -0
  486. package/src/render-system-producer-roots.ts +96 -0
  487. package/src/render-system-residency.ts +159 -0
  488. package/src/render-system.ts +347 -363
  489. package/src/scene/probe-blend.ts +96 -4
  490. package/src/scene/render-scene.ts +349 -280
  491. package/src/ssao-buffers.ts +95 -2
  492. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  493. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  494. package/src/surface/dynamic-input.ts +658 -0
  495. package/src/surface/gpu-driven.ts +147 -0
  496. package/src/surface/submission-observation.ts +517 -0
  497. package/src/systems/skin-palette-allocator.ts +4 -1
  498. package/src/temporal/gpu.ts +101 -17
  499. package/src/temporal/inspection.ts +7 -1
  500. package/src/temporal/standard-scene-data.ts +5 -0
  501. package/src/temporal/target-coverage-attachment.ts +4 -0
  502. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  503. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  504. package/src/transmission/single-layer-medium.ts +322 -0
  505. package/src/typed-render-graph-primitives.ts +70 -2
  506. package/src/volume/component.ts +10 -9
  507. package/src/volume/extract.ts +11 -5
  508. package/src/volume/inspection.ts +3 -0
  509. package/src/volume/passes.ts +87 -4
  510. package/src/volume/resources.ts +2 -1
  511. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  512. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  513. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  514. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  515. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  516. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  517. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  518. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -0,0 +1,226 @@
1
+ import type { CloudQuality } from '../components/cloud-layer';
2
+
3
+ export type CloudTemporalResetReason =
4
+ | 'authoring-generation'
5
+ | 'camera-cut'
6
+ | 'resize'
7
+ | 'recovery'
8
+ | 'time-discontinuity'
9
+ | 'cloud-shadow-revision'
10
+ | 'device-generation'
11
+ | 'history-missing'
12
+ | 'reprojection-outside'
13
+ | 'scene-depth-disocclusion';
14
+
15
+ export interface CloudTemporalSignature {
16
+ readonly sourceKey: string;
17
+ readonly viewId: string;
18
+ readonly authoringGeneration: number;
19
+ readonly cloudShadowRevision: number;
20
+ readonly cameraRevision: number;
21
+ readonly deviceGeneration: number;
22
+ readonly width: number;
23
+ readonly height: number;
24
+ readonly timeSeconds: number;
25
+ readonly quality: CloudQuality;
26
+ /** Scene-depth producer revision used to reject disoccluded history. */
27
+ readonly sceneDepthVersion?: number;
28
+ }
29
+
30
+ export interface CloudHistory {
31
+ readonly width: number;
32
+ readonly height: number;
33
+ readonly signature: string;
34
+ readonly temporal: CloudTemporalSignature;
35
+ readonly generation: number;
36
+ readonly valid: boolean;
37
+ }
38
+
39
+ export interface CloudTemporalDecision {
40
+ readonly reset: boolean;
41
+ readonly reasons: readonly CloudTemporalResetReason[];
42
+ readonly signature: string;
43
+ readonly history: CloudHistory | undefined;
44
+ }
45
+
46
+ export interface CloudTemporalFrame {
47
+ readonly signature: CloudTemporalSignature;
48
+ readonly history: CloudHistory | undefined;
49
+ readonly reset: boolean;
50
+ readonly reasons: readonly CloudTemporalResetReason[];
51
+ }
52
+
53
+ export interface CloudHistoryReprojectionInput {
54
+ readonly currentDepth: number;
55
+ readonly historyDepth: number;
56
+ readonly motion: readonly [number, number];
57
+ readonly currentPixel: readonly [number, number];
58
+ readonly historySize: readonly [number, number];
59
+ readonly depthTolerance?: number;
60
+ }
61
+
62
+ export interface CloudHistoryReprojection {
63
+ readonly accepted: boolean;
64
+ readonly historyUv: readonly [number, number];
65
+ readonly weight: number;
66
+ readonly reason: 'accepted' | 'outside' | 'depth-disocclusion';
67
+ }
68
+
69
+ export function cloudTemporalSignature(input: CloudTemporalSignature): string {
70
+ return [
71
+ 'cloud-temporal-v1',
72
+ input.viewId,
73
+ input.sourceKey,
74
+ input.authoringGeneration,
75
+ input.cloudShadowRevision,
76
+ input.cameraRevision,
77
+ input.deviceGeneration,
78
+ input.width,
79
+ input.height,
80
+ input.timeSeconds,
81
+ input.quality,
82
+ input.sceneDepthVersion ?? 0,
83
+ ].join(':');
84
+ }
85
+
86
+ function sameLayout(left: CloudTemporalSignature, right: CloudTemporalSignature): boolean {
87
+ return left.viewId === right.viewId && left.width === right.width && left.height === right.height;
88
+ }
89
+
90
+ /** Compare the facts that make a cloud history safe to reuse. */
91
+ export function cloudTemporalResetReasons(
92
+ previous: CloudTemporalSignature | undefined,
93
+ next: CloudTemporalSignature,
94
+ options: { readonly cameraCut?: boolean; readonly recovery?: boolean } = {},
95
+ ): readonly CloudTemporalResetReason[] {
96
+ if (previous === undefined) return ['history-missing'];
97
+ const reasons: CloudTemporalResetReason[] = [];
98
+ if (
99
+ previous.sourceKey !== next.sourceKey ||
100
+ previous.authoringGeneration !== next.authoringGeneration
101
+ ) {
102
+ reasons.push('authoring-generation');
103
+ }
104
+ if (previous.cloudShadowRevision !== next.cloudShadowRevision)
105
+ reasons.push('cloud-shadow-revision');
106
+ if (previous.deviceGeneration !== next.deviceGeneration) reasons.push('device-generation');
107
+ if (
108
+ previous.sceneDepthVersion !== undefined &&
109
+ next.sceneDepthVersion !== undefined &&
110
+ previous.sceneDepthVersion !== next.sceneDepthVersion
111
+ ) {
112
+ reasons.push('scene-depth-disocclusion');
113
+ }
114
+ if (!sameLayout(previous, next)) reasons.push('resize');
115
+ if (options.cameraCut === true || previous.cameraRevision !== next.cameraRevision)
116
+ reasons.push('camera-cut');
117
+ const dt = next.timeSeconds - previous.timeSeconds;
118
+ if (!Number.isFinite(dt) || dt < 0 || dt > 0.5) reasons.push('time-discontinuity');
119
+ if (options.recovery === true) reasons.push('recovery');
120
+ return Object.freeze(reasons);
121
+ }
122
+
123
+ export function createCloudHistory(
124
+ signature: CloudTemporalSignature,
125
+ generation: number,
126
+ valid = false,
127
+ ): CloudHistory {
128
+ return Object.freeze({
129
+ width: Math.max(1, Math.floor(signature.width)),
130
+ height: Math.max(1, Math.floor(signature.height)),
131
+ signature: cloudTemporalSignature(signature),
132
+ temporal: Object.freeze({ ...signature }),
133
+ generation,
134
+ valid,
135
+ });
136
+ }
137
+
138
+ /** Per-view histories are keyed by the renderer's view identity. */
139
+ export class CloudHistoryStore {
140
+ private readonly maxViews: number;
141
+ private readonly entries = new Map<
142
+ string,
143
+ { readonly history: CloudHistory; readonly signature: CloudTemporalSignature }
144
+ >();
145
+
146
+ constructor(maxViews = 4) {
147
+ this.maxViews = Math.max(1, Math.floor(maxViews));
148
+ }
149
+
150
+ begin(
151
+ signature: CloudTemporalSignature,
152
+ options: { readonly cameraCut?: boolean; readonly recovery?: boolean } = {},
153
+ ): CloudTemporalDecision {
154
+ const key = signature.viewId;
155
+ const previousEntry = this.entries.get(key);
156
+ const previous = previousEntry?.history;
157
+ const reasons = cloudTemporalResetReasons(previousEntry?.signature, signature, options);
158
+ const reset = reasons.length > 0;
159
+ return Object.freeze({
160
+ reset,
161
+ reasons,
162
+ signature: cloudTemporalSignature(signature),
163
+ history: reset ? undefined : previous,
164
+ });
165
+ }
166
+
167
+ commit(signature: CloudTemporalSignature, history: CloudHistory): void {
168
+ if (
169
+ history.width !== Math.max(1, Math.floor(signature.width)) ||
170
+ history.height !== Math.max(1, Math.floor(signature.height))
171
+ ) {
172
+ this.entries.delete(signature.viewId);
173
+ return;
174
+ }
175
+ this.entries.set(signature.viewId, { history, signature: Object.freeze({ ...signature }) });
176
+ while (this.entries.size > this.maxViews) {
177
+ const oldest = this.entries.keys().next().value as string | undefined;
178
+ if (oldest === undefined) break;
179
+ this.entries.delete(oldest);
180
+ }
181
+ }
182
+
183
+ reset(viewId?: string): void {
184
+ if (viewId === undefined) this.entries.clear();
185
+ else this.entries.delete(viewId);
186
+ }
187
+
188
+ get(viewId: string): CloudHistory | undefined {
189
+ return this.entries.get(viewId)?.history;
190
+ }
191
+
192
+ dispose(): void {
193
+ this.entries.clear();
194
+ }
195
+ }
196
+
197
+ /** Project one current pixel into the previous cloud history. */
198
+ export function reprojectCloudHistory(
199
+ input: CloudHistoryReprojectionInput,
200
+ historyWeight = 0.9,
201
+ ): CloudHistoryReprojection {
202
+ const width = Math.max(1, input.historySize[0] ?? 1);
203
+ const height = Math.max(1, input.historySize[1] ?? 1);
204
+ const uv: [number, number] = [
205
+ ((input.currentPixel[0] ?? 0) - (input.motion[0] ?? 0)) / width,
206
+ ((input.currentPixel[1] ?? 0) - (input.motion[1] ?? 0)) / height,
207
+ ];
208
+ if (uv[0] < 0 || uv[0] > 1 || uv[1] < 0 || uv[1] > 1) {
209
+ return { accepted: false, historyUv: uv, weight: 0, reason: 'outside' };
210
+ }
211
+ const depthTolerance =
212
+ input.depthTolerance ?? Math.max(0.01, Math.abs(input.currentDepth) * 0.02);
213
+ if (
214
+ !Number.isFinite(input.currentDepth) ||
215
+ !Number.isFinite(input.historyDepth) ||
216
+ Math.abs(input.currentDepth - input.historyDepth) > depthTolerance
217
+ ) {
218
+ return { accepted: false, historyUv: uv, weight: 0, reason: 'depth-disocclusion' };
219
+ }
220
+ return {
221
+ accepted: true,
222
+ historyUv: uv,
223
+ weight: Math.min(0.99, Math.max(0, historyWeight)),
224
+ reason: 'accepted',
225
+ };
226
+ }
@@ -0,0 +1,46 @@
1
+ import { defineComponent, type SchemaOf, type ShapeOf } from '@forgeax/engine-ecs';
2
+ import { err, ok, type Result } from '@forgeax/engine-types';
3
+ import { BarrelDistortionInvalidParameterError } from '../errors/render';
4
+
5
+ /** Camera companion that applies the bounded first-order barrel model. */
6
+ export const BarrelDistortion = defineComponent('BarrelDistortion', {
7
+ strength: { type: 'f32', default: 0 },
8
+ centerX: { type: 'f32', default: 0.5 },
9
+ centerY: { type: 'f32', default: 0.5 },
10
+ });
11
+
12
+ export type BarrelDistortionData = ShapeOf<SchemaOf<typeof BarrelDistortion>>;
13
+
14
+ const DEFAULT_BARREL_DISTORTION: BarrelDistortionData = Object.freeze({
15
+ strength: 0,
16
+ centerX: 0.5,
17
+ centerY: 0.5,
18
+ });
19
+
20
+ function invalid(
21
+ field: 'strength' | 'centerX' | 'centerY',
22
+ value: number,
23
+ expected: string,
24
+ ): BarrelDistortionInvalidParameterError {
25
+ return new BarrelDistortionInvalidParameterError({ field, value, expected });
26
+ }
27
+
28
+ /** Validate and detach camera-owned barrel authoring data. */
29
+ export function validateBarrelDistortionParameters(
30
+ input: Partial<BarrelDistortionData> | undefined,
31
+ ): Result<BarrelDistortionData, BarrelDistortionInvalidParameterError> {
32
+ const value = input ?? {};
33
+ const strength = value.strength ?? DEFAULT_BARREL_DISTORTION.strength;
34
+ const centerX = value.centerX ?? DEFAULT_BARREL_DISTORTION.centerX;
35
+ const centerY = value.centerY ?? DEFAULT_BARREL_DISTORTION.centerY;
36
+ if (!Number.isFinite(strength) || strength < 0 || strength > 0.35) {
37
+ return err(invalid('strength', strength, 'finite and in [0, 0.35]'));
38
+ }
39
+ if (!Number.isFinite(centerX) || centerX < 0 || centerX > 1) {
40
+ return err(invalid('centerX', centerX, 'finite and in [0, 1]'));
41
+ }
42
+ if (!Number.isFinite(centerY) || centerY < 0 || centerY > 1) {
43
+ return err(invalid('centerY', centerY, 'finite and in [0, 1]'));
44
+ }
45
+ return ok(Object.freeze({ strength, centerX, centerY }));
46
+ }
@@ -0,0 +1,47 @@
1
+ import { defineComponent, type SchemaOf, type ShapeOf } from '@forgeax/engine-ecs';
2
+
3
+ /** Closed quality lane for the renderer-owned procedural cloud producer. */
4
+ export type CloudQuality = 'low' | 'medium' | 'high';
5
+
6
+ export const CloudQualityValue = Object.freeze({
7
+ low: 0,
8
+ medium: 1,
9
+ high: 2,
10
+ } as const);
11
+
12
+ /**
13
+ * A single World-authored cloud layer.
14
+ *
15
+ * The component contains only source facts. Cache resolution, optical step
16
+ * counts, temporal history and GPU handles are derived by Render and never
17
+ * written back into ECS.
18
+ */
19
+ export const CloudLayer = defineComponent('CloudLayer', {
20
+ /** Stable integer seed for the periodic 3D density field. */
21
+ seed: { type: 'u32', default: 1337 },
22
+ /** World-space lower edge of the layer, in metres. */
23
+ baseHeight: { type: 'f32', default: 120 },
24
+ /** World-space thickness of the layer, in metres. */
25
+ thickness: { type: 'f32', default: 80 },
26
+ /** Horizontal noise scale, in cycles per metre. */
27
+ scale: { type: 'f32', default: 0.004 },
28
+ /** Coverage threshold in [0, 1]. */
29
+ coverage: { type: 'f32', default: 0.48 },
30
+ /** Extinction multiplier in inverse metres. */
31
+ density: { type: 'f32', default: 1 },
32
+ /** World-space wind velocity in metres per second. */
33
+ wind: { type: 'array<f32, 3>', default: new Float32Array([8, 0, 2]) },
34
+ /** Quality controls cache resolution and bounded ray steps. */
35
+ quality: { type: 'f32', default: CloudQualityValue.medium },
36
+ /** Maximum world-space distance represented by the light-space shadow map. */
37
+ shadowRange: { type: 'f32', default: 512 },
38
+ });
39
+
40
+ export type CloudLayerData = ShapeOf<SchemaOf<typeof CloudLayer>>;
41
+
42
+ export function cloudQualityFromF32(value: number): CloudQuality | undefined {
43
+ if (value === CloudQualityValue.low) return 'low';
44
+ if (value === CloudQualityValue.medium) return 'medium';
45
+ if (value === CloudQualityValue.high) return 'high';
46
+ return undefined;
47
+ }
@@ -1,5 +1,7 @@
1
1
  export * from './atmosphere';
2
+ export * from './barrel-distortion';
2
3
  export * from './camera';
4
+ export * from './cloud-layer';
3
5
  export * from './cube-camera';
4
6
  export * from './depth-of-field';
5
7
  export * from './directional-light';
@@ -1,50 +1,23 @@
1
- // @forgeax/engine-render - renderer-owned large instance association.
2
- //
3
- // The ECS component deliberately carries only a stable collection identity.
4
- // Matrix bytes, revision, capacity, dirty ranges, GPU residency and fallback
5
- // policy belong to InstanceCollectionStore, exposed from the same Renderer.
6
- // This keeps large payloads out of the ECS managed BufferPool while retaining
7
- // ordinary query and entity-lifetime semantics.
8
- //
9
- // Authoring example:
10
- //
11
- // const transforms = new Float32Array(instanceCount * 16);
12
- // for (let index = 0; index < instanceCount; index += 1) {
13
- // const offset = index * 16;
14
- // transforms[offset] = 1;
15
- // transforms[offset + 5] = 1;
16
- // transforms[offset + 10] = 1;
17
- // transforms[offset + 15] = 1;
18
- // }
19
- // const collection = renderer.instances.create({
20
- // transforms,
21
- // }).unwrap();
22
- // world.spawn(
23
- // { component: MeshFilter, data: { assetHandle: HANDLE_CUBE } },
24
- // { component: MeshRenderer, data: {} },
25
- // { component: Instances, data: { collectionId: collection.collectionId } },
26
- // );
27
- //
28
- // Updates stay on the renderer owner and publish one revision:
29
- //
30
- // renderer.instances.update(collection.collectionId, {
31
- // start: 12,
32
- // transforms: patch,
33
- // });
34
- //
35
- // Render extraction snapshots the validated packed column-major matrices once
36
- // per frame. Direct, GPU-driven and fallback lanes consume that same detached
37
- // projection; callers never split one logical collection into ECS chunks.
38
-
39
1
  import { defineComponent } from '@forgeax/engine-ecs';
40
- import type { InstanceCollectionData } from '../instances';
41
2
 
42
- /** Per-entity association with a renderer-owned instance collection. */
3
+ /**
4
+ * World-owned local transforms for one explicit instanced renderable.
5
+ * Packed column-major mat4 values compose as entityWorld * instanceLocal.
6
+ * ECS owns copying, mutation and entity lifetime, including large arrays.
7
+ * Renderer extraction derives its own snapshot and GPU residency; neither
8
+ * authoring nor glTF SceneAsset lowering requires a Renderer identity.
9
+ *
10
+ * @example
11
+ * const transforms = new Float32Array(20_000 * 16);
12
+ * for (let i = 0; i < 20_000; i++) {
13
+ * transforms[i * 16] = transforms[i * 16 + 5] =
14
+ * transforms[i * 16 + 10] = transforms[i * 16 + 15] = 1;
15
+ * }
16
+ * const entity = world.spawn({ component: Instances, data: { transforms } }).unwrap();
17
+ * world.set(entity, Instances, { transforms }).unwrap();
18
+ */
43
19
  export const Instances = defineComponent('Instances', {
44
- collectionId: { type: 'u32', default: 0 },
20
+ transforms: { type: 'array<f32>' },
45
21
  });
46
22
 
47
- /** Type-level hint for the `data` object at the Instances spawn site. */
48
- export type InstancesData = InstanceCollectionData;
49
-
50
- export type { InstanceCollectionId } from '../instances';
23
+ export type InstancesData = { readonly transforms: Float32Array };
@@ -41,7 +41,7 @@
41
41
  // composes per instance:
42
42
  // world_position[i] = entity_world * instances_local[i] * vertex_position
43
43
  // `SpriteInstances.transforms[i*16..i*16+15]` is interpreted as a local-
44
- // space transform under the entity, matching the 3D collection projection.
44
+ // space transform under the entity, exactly like `Instances.transforms`.
45
45
  // Set the entity's `Transform` to identity to make `instances_local[i]`
46
46
  // directly world-space.
47
47
  //
@@ -14,7 +14,7 @@ export type {
14
14
  RhiBackendInstrumentation,
15
15
  RhiBackendPack,
16
16
  } from './assembly/backend-contract';
17
- export { EngineEnvironmentError } from './assembly/backend-contract';
17
+ export { EngineEnvironmentError, loadRhiPack } from './assembly/backend-contract';
18
18
  export type { RendererLegacyHostAdapter } from './assembly/host-contract';
19
19
  export type { BundlerOptions };
20
20
 
@@ -53,6 +53,9 @@ export interface DynamicGeometryCandidate {
53
53
  readonly state: DynamicGeometryCandidateState;
54
54
  }
55
55
 
56
+ /** Record-stage lane that consumed a published dynamic-geometry candidate. */
57
+ export type DynamicGeometryRecordStageLane = 'cpu' | 'gpu' | 'mixed';
58
+
56
59
  /** Receipt that ties candidate publication to the sole Renderer FrameReceipt. */
57
60
  export interface DynamicGeometryReceipt {
58
61
  readonly candidateId: string;
@@ -69,6 +72,8 @@ export interface DynamicGeometryReceipt {
69
72
  };
70
73
  /** Whether the Renderer record stage consumed this candidate for this frame. */
71
74
  readonly recordStageConsumed: boolean;
75
+ /** Lane evidence from the exact submitted record stage, when attached. */
76
+ readonly recordStageLane?: DynamicGeometryRecordStageLane;
72
77
  /** Actual frame fixed step; may be newer than the preparation step. */
73
78
  readonly publicationFixedStep?: number;
74
79
  }
@@ -271,6 +276,9 @@ export interface DynamicGeometryLifecycle {
271
276
  worlds?: readonly object[],
272
277
  fixedStep?: number,
273
278
  canPublish?: (candidate: DynamicGeometryCandidate) => boolean,
279
+ recordStageLane?: (
280
+ candidate: DynamicGeometryCandidate,
281
+ ) => DynamicGeometryRecordStageLane | undefined,
274
282
  ): readonly DynamicGeometryReceipt[];
275
283
  invalidateWorld(world: object, completion?: Promise<unknown>): void;
276
284
  invalidateGeneration(generation: number): void;
@@ -610,7 +618,7 @@ export function createDynamicGeometryLifecycle(
610
618
  meshBytes = Math.max(0, meshBytes - record.candidate.meshBytes);
611
619
  return ok(undefined);
612
620
  },
613
- publishFrame(frame, worlds, fixedStep, canPublish) {
621
+ publishFrame(frame, worlds, fixedStep, canPublish, recordStageLane) {
614
622
  if (disposed || frame.deviceGeneration !== currentGeneration) return [];
615
623
  const receipts: DynamicGeometryReceipt[] = [];
616
624
  for (const record of records.values()) {
@@ -630,6 +638,8 @@ export function createDynamicGeometryLifecycle(
630
638
  continue;
631
639
  }
632
640
  if (canPublish !== undefined && !canPublish(record.candidate)) continue;
641
+ const consumedLane =
642
+ canPublish === undefined ? undefined : recordStageLane?.(record.candidate);
633
643
  record.candidate = Object.freeze({ ...record.candidate, state: 'published' as const });
634
644
  const receipt = Object.freeze({
635
645
  candidateId: record.candidate.candidateId,
@@ -642,6 +652,7 @@ export function createDynamicGeometryLifecycle(
642
652
  frameId: frame.frameId,
643
653
  deviceGeneration: frame.deviceGeneration,
644
654
  recordStageConsumed: canPublish !== undefined,
655
+ ...(consumedLane === undefined ? {} : { recordStageLane: consumedLane }),
645
656
  ...(fixedStep === undefined ? {} : { publicationFixedStep: fixedStep }),
646
657
  frame: Object.freeze({ ...frame }),
647
658
  });
@@ -0,0 +1,103 @@
1
+ /** Closed errors produced by the CloudLayer authoring and resource route. */
2
+
3
+ export interface CloudLayerInvalidParameterDetail {
4
+ readonly field: string;
5
+ readonly value: unknown;
6
+ readonly expected: string;
7
+ }
8
+
9
+ export class CloudLayerInvalidParameterError extends Error {
10
+ readonly code = 'cloud-layer-invalid-parameter' as const;
11
+ readonly expected: string;
12
+ readonly hint: string;
13
+ readonly detail: CloudLayerInvalidParameterDetail;
14
+
15
+ constructor(field: string, value: unknown, expected: string) {
16
+ super(`CloudLayer.${field} is invalid`);
17
+ this.name = 'CloudLayerInvalidParameterError';
18
+ this.expected = `CloudLayer.${field} must be ${expected}`;
19
+ this.hint = `set CloudLayer.${field} to ${expected}`;
20
+ this.detail = { field, value, expected };
21
+ }
22
+ }
23
+
24
+ export interface CloudLayerOwnerConflictDetail {
25
+ readonly count: number;
26
+ }
27
+
28
+ export class CloudLayerOwnerConflictError extends Error {
29
+ readonly code = 'cloud-layer-owner-conflict' as const;
30
+ readonly expected = 'at most one CloudLayer owns a World frame';
31
+ readonly hint = 'remove additional CloudLayer owners before extraction';
32
+ readonly detail: CloudLayerOwnerConflictDetail;
33
+
34
+ constructor(count: number) {
35
+ super(`CloudLayer owner cardinality is ${count}`);
36
+ this.name = 'CloudLayerOwnerConflictError';
37
+ this.detail = { count };
38
+ }
39
+ }
40
+
41
+ export interface CloudLayerCacheInvalidDetail {
42
+ readonly sourceKey: string;
43
+ readonly reason: string;
44
+ }
45
+
46
+ export class CloudLayerCacheInvalidError extends Error {
47
+ readonly code = 'cloud-layer-cache-invalid' as const;
48
+ readonly expected = 'the density cache payload matches its reconstructible source';
49
+ readonly hint = 'discard the derived cache and rebuild it from CloudLayer source facts';
50
+ readonly detail: CloudLayerCacheInvalidDetail;
51
+
52
+ constructor(sourceKey: string, reason: string) {
53
+ super(`CloudLayer cache is invalid: ${reason}`);
54
+ this.name = 'CloudLayerCacheInvalidError';
55
+ this.detail = { sourceKey, reason };
56
+ }
57
+ }
58
+
59
+ export interface CloudLayerCapabilityMissingDetail {
60
+ readonly capability: string;
61
+ }
62
+
63
+ export class CloudLayerCapabilityMissingError extends Error {
64
+ readonly code = 'cloud-layer-capability-missing' as const;
65
+ readonly expected = 'the selected backend exposes the capability required by the cloud lane';
66
+ readonly hint =
67
+ 'inspect the capability report, disable the cloud lane on this backend, or retry on a backend with the required capability';
68
+ readonly detail: CloudLayerCapabilityMissingDetail;
69
+
70
+ constructor(capability: string) {
71
+ super(`CloudLayer capability is unavailable: ${capability}`);
72
+ this.name = 'CloudLayerCapabilityMissingError';
73
+ this.detail = { capability };
74
+ }
75
+ }
76
+
77
+ export interface CloudLayerResourceFailureDetail {
78
+ readonly stage: 'cache' | 'shadow' | 'view' | 'history' | 'retire';
79
+ readonly generation: number;
80
+ readonly cause?: unknown;
81
+ }
82
+
83
+ export class CloudLayerResourceFailureError extends Error {
84
+ readonly code = 'cloud-layer-resource-failed' as const;
85
+ readonly expected = 'cloud resources are created, submitted and retired as one generation';
86
+ readonly hint = 'keep the last-known-good cloud generation and retry after recovery';
87
+ readonly detail: CloudLayerResourceFailureDetail;
88
+
89
+ constructor(detail: CloudLayerResourceFailureDetail) {
90
+ super(`CloudLayer ${detail.stage} resource failed at generation ${detail.generation}`);
91
+ this.name = 'CloudLayerResourceFailureError';
92
+ this.detail = detail;
93
+ }
94
+ }
95
+
96
+ export type CloudLayerError =
97
+ | CloudLayerInvalidParameterError
98
+ | CloudLayerOwnerConflictError
99
+ | CloudLayerCacheInvalidError
100
+ | CloudLayerCapabilityMissingError
101
+ | CloudLayerResourceFailureError;
102
+
103
+ export type CloudLayerErrorCode = CloudLayerError['code'];
@@ -30,6 +30,7 @@ import type {
30
30
  import type { AutoExposureError } from '../pipeline/standard-output/auto-exposure/inspection';
31
31
  import type { SceneDataLane, SceneDataSchemaId } from '../temporal/scene-data';
32
32
  import type { TransmissionCapabilityFact } from '../transmission/backdrop';
33
+ import type { CloudLayerError } from './cloud';
33
34
  import type { RecoveryOutcome, RecoveryPhase } from './recover';
34
35
 
35
36
  // Public render errors keep one machine-readable order: closed `code`,
@@ -1392,6 +1393,27 @@ export type DynamicResolutionError =
1392
1393
  | DynamicResolutionRequiresTaaError
1393
1394
  | DynamicResolutionTimingUnavailableError;
1394
1395
 
1396
+ export interface BarrelDistortionInvalidParameterDetail {
1397
+ readonly field: 'width' | 'height' | 'strength' | 'centerX' | 'centerY';
1398
+ readonly value: number;
1399
+ readonly expected: string;
1400
+ }
1401
+
1402
+ export class BarrelDistortionInvalidParameterError extends Error {
1403
+ readonly code = 'barrel-distortion-invalid-parameter' as const;
1404
+ readonly expected: string;
1405
+ readonly hint: string;
1406
+ readonly detail: BarrelDistortionInvalidParameterDetail;
1407
+
1408
+ constructor(detail: BarrelDistortionInvalidParameterDetail) {
1409
+ super(`BarrelDistortion.${detail.field} is invalid`);
1410
+ this.name = 'BarrelDistortionInvalidParameterError';
1411
+ this.expected = `BarrelDistortion.${detail.field} must be ${detail.expected}`;
1412
+ this.hint = `set BarrelDistortion.${detail.field} to a value that is ${detail.expected}`;
1413
+ this.detail = detail;
1414
+ }
1415
+ }
1416
+
1395
1417
  export interface OwnerStageFailedDetail {
1396
1418
  readonly owner: 'environment' | 'temporal' | 'fog' | 'renderer';
1397
1419
  readonly stage: 'extract' | 'prepare' | 'record' | 'finish' | 'submit';
@@ -1839,8 +1861,8 @@ export interface VolumeOwnerConflictDetail {
1839
1861
 
1840
1862
  export class VolumeOwnerConflictError extends Error {
1841
1863
  readonly code = 'volume-owner-conflict' as const;
1842
- readonly expected = 'exactly one global VolumetricFog owner is authored';
1843
- readonly hint = 'remove additional VolumetricFog owners and retry extraction';
1864
+ readonly expected = 'at most eight local VolumetricFog owners per rendered World';
1865
+ readonly hint = 'reduce simultaneously visible volume owners and retry extraction';
1844
1866
  readonly detail: VolumeOwnerConflictDetail;
1845
1867
 
1846
1868
  constructor(ownerCount: number) {
@@ -1894,13 +1916,26 @@ export interface VolumeInvalidParametersDetail {
1894
1916
  export class VolumeInvalidParametersError extends Error {
1895
1917
  readonly code = 'volume-invalid-parameters' as const;
1896
1918
  readonly expected = 'volume parameters remain finite and inside their closed ranges';
1897
- readonly hint = 'repair extinction, albedo, emission, anisotropy, or maxDistance';
1919
+ readonly hint = 'repair extinction, albedo, emission, anisotropy, maxDistance, or sampling';
1898
1920
  readonly detail: VolumeInvalidParametersDetail;
1899
1921
 
1900
- constructor(input: { readonly maxDistance?: number; readonly anisotropy?: number }) {
1901
- const field =
1902
- input.maxDistance !== undefined && input.maxDistance <= 0 ? 'maxDistance' : 'parameters';
1903
- const value = field === 'maxDistance' ? input.maxDistance : input.anisotropy;
1922
+ constructor(input: {
1923
+ readonly maxDistance?: number;
1924
+ readonly anisotropy?: number;
1925
+ readonly sampling?: string;
1926
+ }) {
1927
+ const invalidSampling =
1928
+ input.sampling !== undefined && input.sampling !== 'noise' && input.sampling !== 'density';
1929
+ const field = invalidSampling
1930
+ ? 'sampling'
1931
+ : input.maxDistance !== undefined && input.maxDistance <= 0
1932
+ ? 'maxDistance'
1933
+ : 'parameters';
1934
+ const value = invalidSampling
1935
+ ? input.sampling
1936
+ : field === 'maxDistance'
1937
+ ? input.maxDistance
1938
+ : input.anisotropy;
1904
1939
  super(`volume-invalid-parameters: ${field} is outside the authored range`);
1905
1940
  this.name = 'VolumeInvalidParametersError';
1906
1941
  this.detail = { field, value };
@@ -1981,6 +2016,8 @@ export type RenderError =
1981
2016
  | TaaCapsInsufficientError
1982
2017
  | EnvironmentGenerationFailedError
1983
2018
  | AtmosphereInvalidParameterError
2019
+ | BarrelDistortionInvalidParameterError
2020
+ | CloudLayerError
1984
2021
  | DynamicResolutionInvalidParameterError
1985
2022
  | DynamicResolutionRequiresTaaError
1986
2023
  | DynamicResolutionTimingUnavailableError