@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
@@ -78,18 +78,11 @@ import type { MaterialCookProgramContext } from '@forgeax/engine-pack/material-c
78
78
  // non-renderable state and is skipped
79
79
  // (charter proposition 5; AC-11).
80
80
  //
81
- // Renderer-owned Large Instances:
82
- // `Instances { collectionId }` is an ECS association to the renderer's
83
- // `InstanceCollectionStore`, not an ECS transform-array column. The extract
84
- // tail resolves the identity against that store and snapshots canonical
85
- // transforms together with collection revision, capacity, dirty ranges,
86
- // and residency facts. Invalid or stale associations route the existing
87
- // typed `InstanceCollectionError` through the World error boundary; the
88
- // record stage owns GPU residency and upload decisions.
89
- //
90
- // `SpriteInstances` remains the separate ECS-owned array-view path. Its
91
- // snapshot is intentionally independent from renderer-owned Large Instances,
92
- // so the extract stage does not duplicate collection storage or GPU policy.
81
+ // World owns Instances.transforms. Extraction borrows the managed array during
82
+ // the read phase and retains a detached projection only when its values change.
83
+ // RenderScene accepts that projection with the source publication; recording
84
+ // owns device residency, upload revisions and backend-specific chunking.
85
+ // SpriteInstances remains the independent 2D component and snapshot contract.
93
86
 
94
87
  import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
95
88
  import {
@@ -127,6 +120,7 @@ import type {
127
120
  MaterialPass,
128
121
  MaterialProgramAbi,
129
122
  MaterialRenderState,
123
+ MaterialSurfaceModel,
130
124
  MaterialTextureCoordinates,
131
125
  MaterialTextureValue,
132
126
  MeshLodLevel,
@@ -142,6 +136,7 @@ import {
142
136
  import { buildCubeCameraFaceViews } from './capture/cube-views';
143
137
  import {
144
138
  antialiasFromF32,
139
+ BarrelDistortion,
145
140
  CAMERA_EXPOSURE_MODE_MANUAL,
146
141
  Camera,
147
142
  CubeCamera,
@@ -159,6 +154,7 @@ import {
159
154
  validateCameraBloom,
160
155
  validateDynamicResolutionCamera,
161
156
  } from './components';
157
+ import { validateBarrelDistortionParameters } from './components/barrel-distortion';
162
158
  import { DepthOfField } from './components/depth-of-field';
163
159
  import type { DirectionalShadowQuality } from './components/directional-shadow-filter';
164
160
  import type { LightValidationError } from './components/light-helpers';
@@ -185,7 +181,7 @@ import type {
185
181
  RenderFeatureHiddenEntityReport,
186
182
  RenderFeatureWorldVisibilitySnapshot,
187
183
  } from './features/types';
188
- import type { InstanceCollectionId, InstanceCollectionStore } from './instances';
184
+ import type { InstanceCollectionId, InstanceProjectionStore } from './instances';
189
185
  import type {
190
186
  MeshMaterialBindingDiagnostic,
191
187
  MeshMaterialBindingSource,
@@ -658,15 +654,16 @@ export interface SkyboxSnapshot {
658
654
  }
659
655
 
660
656
  /**
661
- * Resource-owner projection for the single ECS VolumetricFog singleton.
657
+ * Resource-owner projection for an ECS VolumetricFog collection.
662
658
  *
663
659
  * The renderer carries the validated authoring facts and the source POD all
664
660
  * the way to the record stage. No profile flag or source/catalog byte is
665
661
  * allowed to enable the graph: `status: 'available'` is produced only after
666
662
  * the ECS component, its shared TextureAsset, and the volume validator all
667
- * agree on one linear 3D density owner.
663
+ * agree on every linear 3D density owner.
668
664
  */
669
665
  export interface ExtractedVolumetricFog {
666
+ readonly additional?: readonly ExtractedVolumetricFog[];
670
667
  readonly status: 'off' | 'available' | 'degraded';
671
668
  readonly fog?: ValidatedVolumetricFog;
672
669
  readonly densityHandle?: Handle<'TextureAsset', 'shared'>;
@@ -857,8 +854,6 @@ export interface InstancesSnapshot {
857
854
  readonly instanceCount: number;
858
855
  /** Collection revision captured by this detached frame snapshot. */
859
856
  readonly revision?: number;
860
- /** Logical collection capacity at snapshot time. */
861
- readonly capacity?: number;
862
857
  /** Coalesced matrix ordinals dirtied since the previous authoring update. */
863
858
  readonly dirtyRanges?: readonly {
864
859
  readonly start: number;
@@ -944,6 +939,10 @@ export interface MaterialSnapshot {
944
939
  readonly baseColor: Vec3;
945
940
  readonly metallic: number;
946
941
  readonly roughness: number;
942
+ /** Root-owned Surface model used only for typed pass routing. */
943
+ readonly surfaceModel?: MaterialSurfaceModel | undefined;
944
+ /** Whether this material publishes a Deferred pass consumed before the forward-only lane. */
945
+ readonly deferredPass?: boolean | undefined;
947
946
  /** Authored Standard PBR specular color in linear runtime color space. */
948
947
  readonly specularColor?: readonly [number, number, number] | undefined;
949
948
  /**
@@ -1243,6 +1242,8 @@ export interface ExtractedFrame {
1243
1242
  readonly environmentReady: boolean;
1244
1243
  /** One resource-owner volume projection; absent means no authored fog. */
1245
1244
  readonly volumetricFog?: ExtractedVolumetricFog;
1245
+ /** Resource-owner CloudLayer facts selected once at the extract boundary. */
1246
+ readonly cloudLayer?: import('./cloud/extract').ExtractedCloudLayer;
1246
1247
  readonly renderables: RenderableSnapshot[];
1247
1248
  /**
1248
1249
  * Single dispatch list sorted by queue value (ascending, stable sort).
@@ -2459,6 +2460,13 @@ export function resolveMaterialSnapshot(
2459
2460
  baseColor,
2460
2461
  metallic: metallicPv,
2461
2462
  roughness: roughnessPv,
2463
+ ...(resolved.surface?.model === undefined ? {} : { surfaceModel: resolved.surface.model }),
2464
+ deferredPass: allPasses.some(
2465
+ (pass) =>
2466
+ String(
2467
+ (pass.renderState?.tags as Record<string, unknown> | undefined)?.LightMode ?? pass.name,
2468
+ ) === 'Deferred',
2469
+ ),
2462
2470
  ...(specularColorPv !== undefined && {
2463
2471
  specularColor: [
2464
2472
  specularColorPv[0] ?? 1,
@@ -2981,13 +2989,14 @@ export interface PreparedExtractContext {
2981
2989
  request?: {
2982
2990
  readonly vertexColorAvailable?: boolean;
2983
2991
  readonly deformation?: 'rigid' | 'skin';
2992
+ readonly variantSet?: string;
2984
2993
  readonly pass?: 'forward' | 'shadow' | 'depth';
2985
2994
  readonly address?: 'direct' | 'scene-index';
2986
2995
  },
2987
2996
  ) => MaterialShaderArtifact | undefined)
2988
2997
  | undefined;
2989
- /** Renderer-owned canonical source for explicit large instance collections. */
2990
- readonly instanceCollections: InstanceCollectionStore | undefined;
2998
+ /** Renderer-private projection of World-authored instance matrices. */
2999
+ readonly instanceCollections: InstanceProjectionStore | undefined;
2991
3000
  }
2992
3001
 
2993
3002
  const ALL_VISIBLE: VisibilitySnapshot = {
@@ -3004,13 +3013,20 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
3004
3013
  const cameraQuery = world
3005
3014
  .query({
3006
3015
  read: [Camera],
3007
- optional: [MotionBlur, DynamicResolution, ScreenSpaceReflection, DepthOfField],
3016
+ optional: [
3017
+ MotionBlur,
3018
+ DynamicResolution,
3019
+ ScreenSpaceReflection,
3020
+ DepthOfField,
3021
+ BarrelDistortion,
3022
+ ],
3008
3023
  with: [Transform, GlobalTransform],
3009
3024
  })
3010
3025
  .unwrap();
3011
3026
  for (const row of cameraQuery) {
3012
3027
  const cam = row.get(Camera);
3013
3028
  const motionBlur = row.get(MotionBlur);
3029
+ const barrelDistortion = row.get(BarrelDistortion);
3014
3030
  const motionBlurResult = resolveMotionBlurParams(motionBlur);
3015
3031
  if (!motionBlurResult.ok) throw motionBlurResult.error;
3016
3032
  const motionBlurParams = motionBlurResult.value;
@@ -3051,6 +3067,8 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
3051
3067
  const antialias = antialiasFromF32(cam.antialias);
3052
3068
  const dynamicResolutionResult = validateDynamicResolutionCamera(dynamicResolution, antialias);
3053
3069
  if (!dynamicResolutionResult.ok) throw dynamicResolutionResult.error;
3070
+ const barrelDistortionResult = validateBarrelDistortionParameters(barrelDistortion);
3071
+ if (!barrelDistortionResult.ok) throw barrelDistortionResult.error;
3054
3072
  cameras.push({
3055
3073
  entityKey: entity as number,
3056
3074
  ...(target === undefined ? {} : { target }),
@@ -3105,6 +3123,7 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
3105
3123
  targetFps: motionBlurParams.targetFps,
3106
3124
  },
3107
3125
  }),
3126
+ ...(barrelDistortion === undefined ? {} : { barrelDistortion: barrelDistortionResult.value }),
3108
3127
  ...(screenSpaceReflection === undefined
3109
3128
  ? {}
3110
3129
  : {
@@ -3257,11 +3276,12 @@ export function prepareExtractContext(
3257
3276
  request?: {
3258
3277
  readonly vertexColorAvailable?: boolean;
3259
3278
  readonly deformation?: 'rigid' | 'skin';
3279
+ readonly variantSet?: string;
3260
3280
  readonly pass?: 'forward' | 'shadow' | 'depth';
3261
3281
  readonly address?: 'direct' | 'scene-index';
3262
3282
  },
3263
3283
  ) => MaterialShaderArtifact | undefined;
3264
- readonly instanceCollections?: InstanceCollectionStore;
3284
+ readonly instanceCollections?: InstanceProjectionStore;
3265
3285
  } = {},
3266
3286
  ): PreparedExtractContext {
3267
3287
  const renderables = options.renderables ?? 'full';
@@ -3364,6 +3384,7 @@ export function extractVolumeSnapshot(
3364
3384
  const worldTimeSeconds = Number.isFinite(elapsed) ? Math.max(0, elapsed) : 0;
3365
3385
  const query = world.query({ read: [VolumetricFog] }).unwrap();
3366
3386
  const authorings: VolumetricFogAuthoring[] = [];
3387
+ const members: ExtractedVolumetricFog[] = [];
3367
3388
  let selectedLight:
3368
3389
  | {
3369
3390
  readonly entity: EntityHandle;
@@ -3372,15 +3393,9 @@ export function extractVolumeSnapshot(
3372
3393
  readonly spotLightEntity?: EntityHandle;
3373
3394
  }
3374
3395
  | undefined;
3375
- let first:
3376
- | {
3377
- readonly densityHandle: Handle<'TextureAsset', 'shared'>;
3378
- readonly densityAsset: TextureAsset;
3379
- readonly guid: string;
3380
- }
3381
- | undefined;
3382
3396
 
3383
3397
  for (const row of query) {
3398
+ selectedLight = undefined;
3384
3399
  const source = row.get(VolumetricFog);
3385
3400
  if (source.light === null) continue;
3386
3401
  const selected = resolveSelectedVolumetricLight(world, source.light);
@@ -3457,9 +3472,30 @@ export function extractVolumeSnapshot(
3457
3472
  emission: [source.emission[0] ?? 0, source.emission[1] ?? 0, source.emission[2] ?? 0],
3458
3473
  anisotropy: source.anisotropy,
3459
3474
  maxDistance: source.maxDistance,
3475
+ sampling: source.sampling === 1 ? 'density' : 'noise',
3460
3476
  };
3461
3477
  authorings.push(authoring);
3462
- first ??= { densityHandle, densityAsset, guid };
3478
+ members.push({
3479
+ status: 'available',
3480
+ worldTimeSeconds,
3481
+ densityHandle,
3482
+ densityAsset,
3483
+ guid,
3484
+ generation: 1,
3485
+ digest: textureDigest(densityAsset),
3486
+ ...(selectedLight === undefined
3487
+ ? {}
3488
+ : {
3489
+ lightEntity: selectedLight.entity,
3490
+ lightKind: selectedLight.kind,
3491
+ ...(selectedLight.pointLightEntity === undefined
3492
+ ? {}
3493
+ : { pointLightEntity: selectedLight.pointLightEntity }),
3494
+ ...(selectedLight.spotLightEntity === undefined
3495
+ ? {}
3496
+ : { spotLightEntity: selectedLight.spotLightEntity }),
3497
+ }),
3498
+ });
3463
3499
  }
3464
3500
 
3465
3501
  if (authorings.length === 0) return undefined;
@@ -3469,56 +3505,18 @@ export function extractVolumeSnapshot(
3469
3505
  severity: Severity.Error,
3470
3506
  systemName: 'RenderSystem.extract (volumetric-fog)',
3471
3507
  });
3472
- return {
3473
- status: 'degraded',
3474
- worldTimeSeconds,
3475
- ...(first === undefined
3476
- ? {}
3477
- : {
3478
- densityHandle: first.densityHandle,
3479
- densityAsset: first.densityAsset,
3480
- guid: first.guid,
3481
- generation: 1,
3482
- digest: textureDigest(first.densityAsset),
3483
- ...(selectedLight === undefined
3484
- ? {}
3485
- : {
3486
- lightEntity: selectedLight.entity,
3487
- lightKind: selectedLight.kind,
3488
- ...(selectedLight.pointLightEntity === undefined
3489
- ? {}
3490
- : { pointLightEntity: selectedLight.pointLightEntity }),
3491
- ...(selectedLight.spotLightEntity === undefined
3492
- ? {}
3493
- : { spotLightEntity: selectedLight.spotLightEntity }),
3494
- }),
3495
- }),
3496
- };
3508
+ return { ...members[0], status: 'degraded' };
3497
3509
  }
3498
- if (extracted.value.status === 'off' || first === undefined) return { status: 'off' };
3499
- const selectedLightFields =
3500
- selectedLight === undefined
3501
- ? {}
3502
- : {
3503
- lightEntity: selectedLight.entity,
3504
- lightKind: selectedLight.kind,
3505
- ...(selectedLight.pointLightEntity === undefined
3506
- ? {}
3507
- : { pointLightEntity: selectedLight.pointLightEntity }),
3508
- ...(selectedLight.spotLightEntity === undefined
3509
- ? {}
3510
- : { spotLightEntity: selectedLight.spotLightEntity }),
3511
- };
3510
+ if (extracted.value.status === 'off') return { status: 'off' };
3511
+ const validatedMembers = extracted.value.fogs.map((fog, index) => ({
3512
+ ...members[index],
3513
+ status: 'available' as const,
3514
+ fog,
3515
+ }));
3512
3516
  return {
3513
3517
  status: 'available',
3514
- worldTimeSeconds,
3515
- fog: extracted.value.fog,
3516
- densityHandle: first.densityHandle,
3517
- densityAsset: first.densityAsset,
3518
- guid: first.guid,
3519
- generation: 1,
3520
- digest: textureDigest(first.densityAsset),
3521
- ...selectedLightFields,
3518
+ ...validatedMembers[0],
3519
+ additional: validatedMembers.slice(1),
3522
3520
  };
3523
3521
  }
3524
3522
 
@@ -0,0 +1,56 @@
1
+ import type { World } from '@forgeax/engine-ecs';
2
+ import type { RenderSystemInternals } from './record/render-context';
3
+ import type { FramePresentation } from './render-contract';
4
+ import type { DispatchEntry, RenderableSnapshot } from './render-system-extract';
5
+ import { observeMaterialResidency } from './render-system-residency';
6
+
7
+ export interface FramePresentationProjection {
8
+ readonly renderables: readonly RenderableSnapshot[];
9
+ readonly presentation: FramePresentation;
10
+ }
11
+
12
+ /**
13
+ * Derive the startup presentation candidate from the current display workset.
14
+ * Shadow-only retained rows are deliberately excluded, while material facts
15
+ * still come from the producer-owned residency projection.
16
+ */
17
+ export function projectFramePresentation(input: {
18
+ readonly hasCamera: boolean;
19
+ readonly environmentReady: boolean;
20
+ readonly hasEnvironment: boolean;
21
+ readonly submissionRenderables: readonly RenderableSnapshot[];
22
+ readonly submissionDispatch: readonly DispatchEntry[];
23
+ readonly preparedWorlds: readonly World[];
24
+ readonly internals: RenderSystemInternals;
25
+ }): FramePresentationProjection {
26
+ const displayRenderableIndices = new Set<number>();
27
+ for (const entry of input.submissionDispatch) {
28
+ if (entry.renderableIndex === undefined) continue;
29
+ if (entry.tags.LightMode !== 'ShadowCaster')
30
+ displayRenderableIndices.add(entry.renderableIndex);
31
+ }
32
+ const renderables = input.submissionRenderables.filter(
33
+ (_, index) =>
34
+ displayRenderableIndices.has(index) &&
35
+ input.submissionRenderables[index]?.authorVisible !== false,
36
+ );
37
+
38
+ let presentation: FramePresentation = 'ready';
39
+ if (input.hasCamera && (!input.environmentReady || !input.hasEnvironment)) {
40
+ presentation = 'pending';
41
+ } else if (input.hasCamera) {
42
+ for (const renderable of renderables) {
43
+ const materialWorld = input.preparedWorlds[renderable.worldId];
44
+ for (const material of renderable.materials) {
45
+ if (
46
+ observeMaterialResidency(materialWorld, material, input.internals).readiness === 'pending'
47
+ ) {
48
+ presentation = 'pending';
49
+ break;
50
+ }
51
+ }
52
+ if (presentation === 'pending') break;
53
+ }
54
+ }
55
+ return { renderables, presentation };
56
+ }
@@ -0,0 +1,96 @@
1
+ export type RendererProducerRootKind =
2
+ | 'backend-surface'
3
+ | 'shader-material-pipeline'
4
+ | 'mesh-texture-sampler'
5
+ | 'render-scene'
6
+ | 'gpu-driven'
7
+ | 'feature'
8
+ | 'external-source'
9
+ | 'render-graph'
10
+ | 'target-history'
11
+ | 'observation-lease';
12
+
13
+ export interface RendererProducerRoot {
14
+ readonly kind: RendererProducerRootKind;
15
+ readonly owner: string;
16
+ readonly candidateScope: 'device-scope';
17
+ readonly visibility: 'visible-workset' | 'non-visible-lazy';
18
+ readonly disabledWork: 'zero' | 'lazy';
19
+ }
20
+
21
+ const PRODUCER_ROOT_MATRIX: readonly RendererProducerRoot[] = Object.freeze([
22
+ {
23
+ kind: 'backend-surface',
24
+ owner: 'backend-surface-owner',
25
+ candidateScope: 'device-scope',
26
+ visibility: 'visible-workset',
27
+ disabledWork: 'zero',
28
+ },
29
+ {
30
+ kind: 'shader-material-pipeline',
31
+ owner: 'shader-material-pipeline-owner',
32
+ candidateScope: 'device-scope',
33
+ visibility: 'visible-workset',
34
+ disabledWork: 'zero',
35
+ },
36
+ {
37
+ kind: 'mesh-texture-sampler',
38
+ owner: 'gpu-residency',
39
+ candidateScope: 'device-scope',
40
+ visibility: 'visible-workset',
41
+ disabledWork: 'lazy',
42
+ },
43
+ {
44
+ kind: 'render-scene',
45
+ owner: 'persistent-render-scene',
46
+ candidateScope: 'device-scope',
47
+ visibility: 'visible-workset',
48
+ disabledWork: 'zero',
49
+ },
50
+ {
51
+ kind: 'gpu-driven',
52
+ owner: 'gpu-driven-production',
53
+ candidateScope: 'device-scope',
54
+ visibility: 'visible-workset',
55
+ disabledWork: 'zero',
56
+ },
57
+ {
58
+ kind: 'feature',
59
+ owner: 'render-feature-host',
60
+ candidateScope: 'device-scope',
61
+ visibility: 'visible-workset',
62
+ disabledWork: 'lazy',
63
+ },
64
+ {
65
+ kind: 'external-source',
66
+ owner: 'external-source-owner',
67
+ candidateScope: 'device-scope',
68
+ visibility: 'non-visible-lazy',
69
+ disabledWork: 'zero',
70
+ },
71
+ {
72
+ kind: 'render-graph',
73
+ owner: 'typed-frame-graph',
74
+ candidateScope: 'device-scope',
75
+ visibility: 'visible-workset',
76
+ disabledWork: 'zero',
77
+ },
78
+ {
79
+ kind: 'target-history',
80
+ owner: 'temporal-target-owner',
81
+ candidateScope: 'device-scope',
82
+ visibility: 'visible-workset',
83
+ disabledWork: 'zero',
84
+ },
85
+ {
86
+ kind: 'observation-lease',
87
+ owner: 'render-observation-owner',
88
+ candidateScope: 'device-scope',
89
+ visibility: 'non-visible-lazy',
90
+ disabledWork: 'zero',
91
+ },
92
+ ]);
93
+
94
+ export function createRendererProducerRootMatrix(): readonly RendererProducerRoot[] {
95
+ return PRODUCER_ROOT_MATRIX;
96
+ }
@@ -0,0 +1,159 @@
1
+ import { resolveAssetHandle } from '@forgeax/engine-assets-runtime';
2
+ import type { World } from '@forgeax/engine-ecs';
3
+ import {
4
+ deriveTextureLayout,
5
+ type MaterialAsset,
6
+ type SamplerAsset,
7
+ type TextureAsset,
8
+ toShared,
9
+ } from '@forgeax/engine-types';
10
+ import type {
11
+ MeshMaterialBindingPreparationFailure,
12
+ MeshMaterialBindingResidency,
13
+ } from './mesh-material-bindings';
14
+ import type { RenderSystemInternals } from './record/render-context';
15
+ import { materialSamplerHandles, materialTextureHandles } from './recovery/render-system-candidate';
16
+ import type { MaterialSnapshot } from './render-system-extract';
17
+
18
+ function preparationFailureFrom(error: unknown): MeshMaterialBindingPreparationFailure | undefined {
19
+ if (typeof error !== 'object' || error === null) return undefined;
20
+ const value = error as {
21
+ readonly code?: unknown;
22
+ readonly expected?: unknown;
23
+ readonly hint?: unknown;
24
+ readonly detail?: unknown;
25
+ };
26
+ if (
27
+ typeof value.code !== 'string' ||
28
+ typeof value.expected !== 'string' ||
29
+ typeof value.hint !== 'string'
30
+ ) {
31
+ return undefined;
32
+ }
33
+ const detail =
34
+ typeof value.detail === 'object' && value.detail !== null
35
+ ? { ...(value.detail as Record<string, unknown>) }
36
+ : undefined;
37
+ return {
38
+ code: value.code,
39
+ expected: value.expected,
40
+ hint: value.hint,
41
+ ...(detail === undefined ? {} : { detail }),
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Project producer-owned material and GPU-store state into the renderer's one
47
+ * observation surface. This is recomputed from detached frame snapshots; no
48
+ * readiness map is retained by RenderSystem. A producer failure with an
49
+ * already resident resource remains last-known-good.
50
+ */
51
+ export function observeMaterialResidency(
52
+ world: World | undefined,
53
+ material: MaterialSnapshot,
54
+ internals: RenderSystemInternals,
55
+ ): MeshMaterialBindingResidency {
56
+ const textures: Array<{ readonly handle: number; readonly mipLevelCount: number }> = [];
57
+ const samplers: Array<{ readonly handle: number; readonly resident: boolean }> = [];
58
+ let pending = false;
59
+ let resident = false;
60
+ let failure: MeshMaterialBindingPreparationFailure | undefined;
61
+ const keepFailure = (error: unknown): void => {
62
+ if (failure === undefined) failure = preparationFailureFrom(error);
63
+ };
64
+
65
+ if (world === undefined) {
66
+ pending = true;
67
+ } else {
68
+ const materialHandle = material.materialHandle;
69
+ if (materialHandle !== undefined && materialHandle !== 0) {
70
+ const materialResult = resolveAssetHandle<MaterialAsset>(
71
+ world,
72
+ toShared<'MaterialAsset'>(materialHandle),
73
+ );
74
+ if (!materialResult.ok) {
75
+ keepFailure(materialResult.error);
76
+ } else {
77
+ const guid = internals.assets.guidOf(materialResult.value);
78
+ if (guid !== undefined) {
79
+ const readiness = internals.assets.getMaterialReadiness(guid);
80
+ if (readiness?.status === 'Error') keepFailure(readiness.error);
81
+ const load = internals.assets.loadState.get(guid);
82
+ if (load?.status === 'provisional') pending = true;
83
+ }
84
+ }
85
+ }
86
+
87
+ for (const handle of materialTextureHandles(material)) {
88
+ const existing = internals.gpuStore.getTextureGpuView(handle, world);
89
+ const pod = resolveAssetHandle<TextureAsset>(world, handle);
90
+ if (!pod.ok) {
91
+ keepFailure(pod.error);
92
+ continue;
93
+ }
94
+ let view = existing;
95
+ if (view === undefined) {
96
+ const prepared = internals.gpuStore.ensureResident(handle, pod.value, world);
97
+ if (!prepared.ok) keepFailure(prepared.error);
98
+ view = internals.gpuStore.getTextureGpuView(handle, world);
99
+ }
100
+ if (view === undefined) {
101
+ pending = failure === undefined;
102
+ continue;
103
+ }
104
+ const textureLayout = deriveTextureLayout({
105
+ shape: pod.value.shape,
106
+ format: pod.value.format,
107
+ mips: pod.value.mips,
108
+ });
109
+ if (!textureLayout.ok) {
110
+ keepFailure(textureLayout.error);
111
+ continue;
112
+ }
113
+ resident = true;
114
+ textures.push({
115
+ handle: Number(handle),
116
+ mipLevelCount: Math.max(1, textureLayout.value.levels.length),
117
+ });
118
+ }
119
+
120
+ for (const handle of materialSamplerHandles(material)) {
121
+ const pod = resolveAssetHandle<SamplerAsset>(world, handle);
122
+ if (!pod.ok) {
123
+ keepFailure(pod.error);
124
+ samplers.push({ handle: Number(handle), resident: false });
125
+ continue;
126
+ }
127
+ const prepared = internals.gpuStore.ensureSamplerResident(handle, pod.value, world);
128
+ if (!prepared.ok) {
129
+ keepFailure(prepared.error);
130
+ samplers.push({ handle: Number(handle), resident: false });
131
+ } else {
132
+ resident = true;
133
+ samplers.push({ handle: Number(handle), resident: true });
134
+ }
135
+ }
136
+ // Video views are supplied by the renderer-owned dynamic store at record
137
+ // time. A previously uploaded view is a producer-owned last-known-good
138
+ // fact; absence means the visible workset still needs a decodable frame.
139
+ for (const clip of material.videoTextureFields?.values() ?? []) {
140
+ if (internals.dynamicTextureStore?.getView(clip) === undefined) pending = true;
141
+ else resident = true;
142
+ }
143
+ }
144
+
145
+ const readiness =
146
+ failure === undefined
147
+ ? pending
148
+ ? 'pending'
149
+ : 'ready'
150
+ : resident
151
+ ? 'last-known-good'
152
+ : 'failed';
153
+ return {
154
+ readiness,
155
+ samplers,
156
+ textures,
157
+ ...(failure === undefined ? {} : { preparationFailure: failure }),
158
+ };
159
+ }