@forgeax/engine-render 0.1.33 → 0.1.35

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 (624) hide show
  1. package/README.md +1062 -127
  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/device-feature-admission.d.ts +2 -2
  11. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  12. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  15. package/dist/assembly/factory.d.ts +1 -1
  16. package/dist/assembly/factory.d.ts.map +1 -1
  17. package/dist/assembly/host-contract.d.ts +6 -5
  18. package/dist/assembly/host-contract.d.ts.map +1 -1
  19. package/dist/assembly/material/assembly.d.ts.map +1 -1
  20. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  21. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  22. package/dist/assembly/material-shader-policy.d.ts +16 -2
  23. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  24. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  26. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  27. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  28. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  29. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  30. package/dist/assembly/render-target-host.d.ts +5 -0
  31. package/dist/assembly/render-target-host.d.ts.map +1 -1
  32. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  33. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  34. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  35. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  36. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  37. package/dist/assembly/renderer-inspection.d.ts +11 -0
  38. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  41. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  42. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +1 -1
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  46. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  47. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  48. package/dist/assembly/webgpu-renderer.d.ts +2 -1
  49. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  50. package/dist/authoring.mjs +2 -4
  51. package/dist/authoring.mjs.map +1 -1
  52. package/dist/barrel-distortion.d.ts +47 -0
  53. package/dist/barrel-distortion.d.ts.map +1 -0
  54. package/dist/chunk-3XUBWRY2.mjs +1842 -0
  55. package/dist/chunk-3XUBWRY2.mjs.map +1 -0
  56. package/dist/{chunk-OO3DRYK7.mjs → chunk-G6HDNGY7.mjs} +2400 -1767
  57. package/dist/chunk-G6HDNGY7.mjs.map +1 -0
  58. package/dist/{chunk-ZDQWGQW7.mjs → chunk-LM5IE7GF.mjs} +4 -4
  59. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
  60. package/dist/{chunk-VOZWDM3L.mjs → chunk-LNIUIKQ7.mjs} +1514 -498
  61. package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
  62. package/dist/chunk-MXTWKZO4.mjs +3268 -0
  63. package/dist/chunk-MXTWKZO4.mjs.map +1 -0
  64. package/dist/chunk-MZ4C7EHF.mjs +6942 -0
  65. package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
  66. package/dist/chunk-RIPAEGI6.mjs +48 -0
  67. package/dist/chunk-RIPAEGI6.mjs.map +1 -0
  68. package/dist/{chunk-LEAXOMYJ.mjs → chunk-SGPUJW3F.mjs} +117 -5
  69. package/dist/chunk-SGPUJW3F.mjs.map +1 -0
  70. package/dist/{chunk-PA5DRJNI.mjs → chunk-X2KA6WHM.mjs} +29 -4
  71. package/dist/chunk-X2KA6WHM.mjs.map +1 -0
  72. package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
  73. package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
  74. package/dist/cloud/density.d.ts +55 -0
  75. package/dist/cloud/density.d.ts.map +1 -0
  76. package/dist/cloud/extract.d.ts +25 -0
  77. package/dist/cloud/extract.d.ts.map +1 -0
  78. package/dist/cloud/feature.d.ts +57 -0
  79. package/dist/cloud/feature.d.ts.map +1 -0
  80. package/dist/cloud/frame-context.d.ts +8 -0
  81. package/dist/cloud/frame-context.d.ts.map +1 -0
  82. package/dist/cloud/inspection.d.ts +59 -0
  83. package/dist/cloud/inspection.d.ts.map +1 -0
  84. package/dist/cloud/optics.d.ts +56 -0
  85. package/dist/cloud/optics.d.ts.map +1 -0
  86. package/dist/cloud/parameters.d.ts +73 -0
  87. package/dist/cloud/parameters.d.ts.map +1 -0
  88. package/dist/cloud/resources.d.ts +60 -0
  89. package/dist/cloud/resources.d.ts.map +1 -0
  90. package/dist/cloud/shadow.d.ts +42 -0
  91. package/dist/cloud/shadow.d.ts.map +1 -0
  92. package/dist/cloud/temporal.d.ts +74 -0
  93. package/dist/cloud/temporal.d.ts.map +1 -0
  94. package/dist/components/barrel-distortion.d.ts +13 -0
  95. package/dist/components/barrel-distortion.d.ts.map +1 -0
  96. package/dist/components/cloud-layer.d.ts +29 -0
  97. package/dist/components/cloud-layer.d.ts.map +1 -0
  98. package/dist/components/index.d.ts +2 -0
  99. package/dist/components/index.d.ts.map +1 -1
  100. package/dist/components/instances.d.ts +20 -6
  101. package/dist/components/instances.d.ts.map +1 -1
  102. package/dist/construct-renderer.d.ts +1 -1
  103. package/dist/construct-renderer.d.ts.map +1 -1
  104. package/dist/construct-renderer.mjs +8406 -5785
  105. package/dist/construct-renderer.mjs.map +1 -1
  106. package/dist/device/gpu-residency.d.ts +19 -19
  107. package/dist/device/gpu-residency.d.ts.map +1 -1
  108. package/dist/dynamic-geometry.d.ts +5 -1
  109. package/dist/dynamic-geometry.d.ts.map +1 -1
  110. package/dist/errors/cloud.d.ts +59 -0
  111. package/dist/errors/cloud.d.ts.map +1 -0
  112. package/dist/errors/render.d.ts +20 -5
  113. package/dist/errors/render.d.ts.map +1 -1
  114. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  115. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  116. package/dist/extract/camera.d.ts.map +1 -1
  117. package/dist/extract/contracts.d.ts +5 -1
  118. package/dist/extract/contracts.d.ts.map +1 -1
  119. package/dist/extract/material-context.d.ts +7 -0
  120. package/dist/extract/material-context.d.ts.map +1 -0
  121. package/dist/features/barrel-distortion.d.ts +29 -0
  122. package/dist/features/barrel-distortion.d.ts.map +1 -0
  123. package/dist/features/error-reporting.d.ts +6 -2
  124. package/dist/features/error-reporting.d.ts.map +1 -1
  125. package/dist/features/host.d.ts +15 -0
  126. package/dist/features/host.d.ts.map +1 -1
  127. package/dist/features/plan.d.ts +10 -0
  128. package/dist/features/plan.d.ts.map +1 -1
  129. package/dist/features/render-graph-contribution.d.ts +5 -0
  130. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  131. package/dist/features/render-graph-raster.d.ts +1 -0
  132. package/dist/features/render-graph-raster.d.ts.map +1 -1
  133. package/dist/features/targets.d.ts +2 -0
  134. package/dist/features/targets.d.ts.map +1 -1
  135. package/dist/features/types.d.ts +48 -0
  136. package/dist/features/types.d.ts.map +1 -1
  137. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  138. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  139. package/dist/glyph-text-layout-system.d.ts +1 -1
  140. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  141. package/dist/gpu-dirty-ranges.d.ts +11 -0
  142. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  143. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  144. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  145. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  146. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  147. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  148. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  149. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  150. package/dist/gpu-driven/production-raster.d.ts +47 -3
  151. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  152. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  153. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  154. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  155. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  156. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  157. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  158. package/dist/gpu-scene.d.ts +5 -0
  159. package/dist/gpu-scene.d.ts.map +1 -1
  160. package/dist/hdrp-buffers.d.ts +2 -2
  161. package/dist/hdrp-buffers.d.ts.map +1 -1
  162. package/dist/ibl/frame-resources.d.ts.map +1 -1
  163. package/dist/ibl/skylight-bind-group.d.ts +14 -5
  164. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  165. package/dist/index.d.ts +30 -7
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.mjs +780 -9
  168. package/dist/index.mjs.map +1 -1
  169. package/dist/inspection-types.d.ts +135 -1
  170. package/dist/inspection-types.d.ts.map +1 -1
  171. package/dist/instance-buffer-cache.d.ts +4 -4
  172. package/dist/instance-buffer-cache.d.ts.map +1 -1
  173. package/dist/instances.d.ts +47 -100
  174. package/dist/instances.d.ts.map +1 -1
  175. package/dist/internal.mjs +7 -8
  176. package/dist/internal.mjs.map +1 -1
  177. package/dist/pbr-pipeline.d.ts +22 -4
  178. package/dist/pbr-pipeline.d.ts.map +1 -1
  179. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  180. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  181. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  182. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  183. package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
  184. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
  185. package/dist/pipeline/standard-output/resources.d.ts +2 -2
  186. package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
  187. package/dist/pipeline/standard-output/types.d.ts +4 -2
  188. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  189. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  190. package/dist/pipeline/standard-post.d.ts.map +1 -1
  191. package/dist/pipeline-builder.d.ts +1 -1
  192. package/dist/pipeline-builder.d.ts.map +1 -1
  193. package/dist/plugin.d.ts.map +1 -1
  194. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  195. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  196. package/dist/publication/contract.d.ts +77 -0
  197. package/dist/publication/contract.d.ts.map +1 -0
  198. package/dist/publication/dependencies.d.ts +7 -0
  199. package/dist/publication/dependencies.d.ts.map +1 -0
  200. package/dist/publication/prepare-geometry.d.ts +9 -0
  201. package/dist/publication/prepare-geometry.d.ts.map +1 -0
  202. package/dist/publication/programs.d.ts +5 -0
  203. package/dist/publication/programs.d.ts.map +1 -0
  204. package/dist/publication/publisher.d.ts +33 -0
  205. package/dist/publication/publisher.d.ts.map +1 -0
  206. package/dist/publication/receiver.d.ts +29 -0
  207. package/dist/publication/receiver.d.ts.map +1 -0
  208. package/dist/publication/resource-scope.d.ts +18 -0
  209. package/dist/publication/resource-scope.d.ts.map +1 -0
  210. package/dist/publication/targets.d.ts +33 -0
  211. package/dist/publication/targets.d.ts.map +1 -0
  212. package/dist/publication/video.d.ts +5 -0
  213. package/dist/publication/video.d.ts.map +1 -0
  214. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  215. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  216. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  218. package/dist/record/fold-buckets.d.ts +95 -0
  219. package/dist/record/fold-buckets.d.ts.map +1 -0
  220. package/dist/record/fold-instance-buffer.d.ts +6 -0
  221. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  222. package/dist/record/frame-lighting.d.ts +1 -0
  223. package/dist/record/frame-lighting.d.ts.map +1 -1
  224. package/dist/record/frame-snapshot.d.ts +43 -9
  225. package/dist/record/frame-snapshot.d.ts.map +1 -1
  226. package/dist/record/frame.d.ts +15 -65
  227. package/dist/record/frame.d.ts.map +1 -1
  228. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  229. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  230. package/dist/record/gpu-timing.d.ts +8 -0
  231. package/dist/record/gpu-timing.d.ts.map +1 -1
  232. package/dist/record/helpers.d.ts +2 -2
  233. package/dist/record/helpers.d.ts.map +1 -1
  234. package/dist/record/main-pass-geometry.d.ts +22 -6
  235. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  236. package/dist/record/main-pass-material.d.ts +14 -10
  237. package/dist/record/main-pass-material.d.ts.map +1 -1
  238. package/dist/record/main-pass-sprite-draws.d.ts +3 -16
  239. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  240. package/dist/record/main-pass.d.ts +13 -2
  241. package/dist/record/main-pass.d.ts.map +1 -1
  242. package/dist/record/motion-blur-receipt.d.ts +11 -0
  243. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  244. package/dist/record/prepared-material-bindings.d.ts +3 -3
  245. package/dist/record/prepared-material-bindings.d.ts.map +1 -1
  246. package/dist/record/probe-blend-buffer.d.ts +16 -0
  247. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  248. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  249. package/dist/record/render-context.d.ts +24 -5
  250. package/dist/record/render-context.d.ts.map +1 -1
  251. package/dist/record/shadow-pass.d.ts +2 -0
  252. package/dist/record/shadow-pass.d.ts.map +1 -1
  253. package/dist/record/skybox-post-pass.d.ts +1 -1
  254. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  255. package/dist/record/sprite-instance-buffer.d.ts +31 -0
  256. package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
  257. package/dist/record/target-capture-graph.d.ts +19 -0
  258. package/dist/record/target-capture-graph.d.ts.map +1 -0
  259. package/dist/record/typed-frame-graph.d.ts +24 -15
  260. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  261. package/dist/record/view-ubo.d.ts +11 -3
  262. package/dist/record/view-ubo.d.ts.map +1 -1
  263. package/dist/record/volume-params.d.ts +9 -0
  264. package/dist/record/volume-params.d.ts.map +1 -0
  265. package/dist/recovery/render-system-candidate.d.ts +14 -4
  266. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  267. package/dist/reflection/record-owner.d.ts.map +1 -1
  268. package/dist/render-contract.d.ts +46 -5
  269. package/dist/render-contract.d.ts.map +1 -1
  270. package/dist/render-graph-primitives.d.ts.map +1 -1
  271. package/dist/render-pipeline.d.ts +103 -2
  272. package/dist/render-pipeline.d.ts.map +1 -1
  273. package/dist/render-system-extract-tail.d.ts +3 -2
  274. package/dist/render-system-extract-tail.d.ts.map +1 -1
  275. package/dist/render-system-extract.d.ts +18 -9
  276. package/dist/render-system-extract.d.ts.map +1 -1
  277. package/dist/render-system-presentation.d.ts +23 -0
  278. package/dist/render-system-presentation.d.ts.map +1 -0
  279. package/dist/render-system-producer-roots.d.ts +10 -0
  280. package/dist/render-system-producer-roots.d.ts.map +1 -0
  281. package/dist/render-system-projections.d.ts +3 -2
  282. package/dist/render-system-projections.d.ts.map +1 -1
  283. package/dist/render-system-residency.d.ts +12 -0
  284. package/dist/render-system-residency.d.ts.map +1 -0
  285. package/dist/render-system.d.ts +22 -21
  286. package/dist/render-system.d.ts.map +1 -1
  287. package/dist/scene/probe-blend.d.ts +27 -0
  288. package/dist/scene/probe-blend.d.ts.map +1 -1
  289. package/dist/scene/render-scene.d.ts +18 -7
  290. package/dist/scene/render-scene.d.ts.map +1 -1
  291. package/dist/scene/render-source.d.ts +42 -0
  292. package/dist/scene/render-source.d.ts.map +1 -0
  293. package/dist/scene/source-systems.d.ts +6 -0
  294. package/dist/scene/source-systems.d.ts.map +1 -0
  295. package/dist/ssao-buffers.d.ts +9 -0
  296. package/dist/ssao-buffers.d.ts.map +1 -1
  297. package/dist/surface/dynamic-input.d.ts +133 -0
  298. package/dist/surface/dynamic-input.d.ts.map +1 -0
  299. package/dist/surface/gpu-driven.d.ts +41 -0
  300. package/dist/surface/gpu-driven.d.ts.map +1 -0
  301. package/dist/surface/submission-observation.d.ts +136 -0
  302. package/dist/surface/submission-observation.d.ts.map +1 -0
  303. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  304. package/dist/systems/skin-palette-types.d.ts +10 -0
  305. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  306. package/dist/systems/transparent-dispatch.d.ts +2 -2
  307. package/dist/systems/transparent-dispatch.d.ts.map +1 -1
  308. package/dist/systems/transparent-sort-config.d.ts +2 -1
  309. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  310. package/dist/temporal/gpu.d.ts +13 -1
  311. package/dist/temporal/gpu.d.ts.map +1 -1
  312. package/dist/temporal/index.mjs +6 -7
  313. package/dist/temporal/inspection.d.ts.map +1 -1
  314. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  315. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  316. package/dist/transmission/single-layer-medium.d.ts +89 -0
  317. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  318. package/dist/typed-render-graph-primitives.d.ts +14 -2
  319. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  320. package/dist/volume/component.d.ts +9 -4
  321. package/dist/volume/component.d.ts.map +1 -1
  322. package/dist/volume/extract.d.ts +1 -1
  323. package/dist/volume/extract.d.ts.map +1 -1
  324. package/dist/volume/inspection.d.ts +2 -0
  325. package/dist/volume/inspection.d.ts.map +1 -1
  326. package/dist/volume/passes.d.ts +4 -1
  327. package/dist/volume/passes.d.ts.map +1 -1
  328. package/dist/volume/resources.d.ts.map +1 -1
  329. package/package.json +22 -21
  330. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  331. package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
  332. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  333. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  334. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  335. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  336. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  337. package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
  338. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  339. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  340. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  341. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +5 -6
  348. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  349. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  350. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  351. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  352. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  353. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  354. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  355. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  356. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  357. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  358. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  359. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  360. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  361. package/src/__tests__/instances-store.unit.test.ts +97 -305
  362. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  363. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
  364. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +145 -0
  365. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  366. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  367. package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
  368. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  369. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  370. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  371. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  372. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  373. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  374. package/src/__tests__/physical-clearcoat.integration.test.ts +66 -8
  375. package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
  376. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  377. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  378. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  379. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  380. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  381. package/src/__tests__/render-error-code-owner.test-d.ts +8 -0
  382. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  383. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  384. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  385. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  386. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  387. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  388. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  389. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  390. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  391. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  392. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -8
  393. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  394. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  395. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  396. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  397. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  398. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  399. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  400. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  401. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  402. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  403. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  404. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  405. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  406. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  407. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  408. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  409. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  410. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  411. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  412. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  413. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  414. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  415. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  416. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  417. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  418. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  419. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  420. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  421. package/src/assembly/backend-contract.ts +30 -0
  422. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  423. package/src/assembly/canvas-draw-guard.ts +11 -0
  424. package/src/assembly/cloud-shadow-entry.ts +22 -0
  425. package/src/assembly/device-feature-admission.ts +2 -2
  426. package/src/assembly/dynamic-geometry-host.ts +65 -37
  427. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  428. package/src/assembly/factory.ts +2 -30
  429. package/src/assembly/host-contract.ts +8 -5
  430. package/src/assembly/material/assembly.ts +25 -13
  431. package/src/assembly/material/pipeline-helpers.ts +53 -12
  432. package/src/assembly/material-shader-policy.ts +55 -0
  433. package/src/assembly/material-shader-prewarm.ts +21 -10
  434. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  435. package/src/assembly/recovery/renderer-recover.ts +50 -18
  436. package/src/assembly/render-feature-post-processes.ts +54 -0
  437. package/src/assembly/render-target-host.ts +57 -47
  438. package/src/assembly/renderer-facade.ts +7 -2
  439. package/src/assembly/renderer-feature-inspection.ts +8 -2
  440. package/src/assembly/renderer-frame-transaction.ts +23 -0
  441. package/src/assembly/renderer-inspection.ts +28 -0
  442. package/src/assembly/skin-palette-owner.ts +1 -1
  443. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  444. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  445. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  446. package/src/assembly/webgpu-ready.ts +116 -62
  447. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  448. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  449. package/src/assembly/webgpu-renderer.ts +303 -313
  450. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  451. package/src/barrel-distortion.ts +247 -0
  452. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  453. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  454. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  455. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  456. package/src/cloud/density.ts +600 -0
  457. package/src/cloud/extract.ts +110 -0
  458. package/src/cloud/feature.ts +1810 -0
  459. package/src/cloud/frame-context.ts +42 -0
  460. package/src/cloud/inspection.ts +130 -0
  461. package/src/cloud/optics.ts +285 -0
  462. package/src/cloud/parameters.ts +255 -0
  463. package/src/cloud/resources.ts +122 -0
  464. package/src/cloud/shadow.ts +167 -0
  465. package/src/cloud/temporal.ts +226 -0
  466. package/src/components/barrel-distortion.ts +46 -0
  467. package/src/components/cloud-layer.ts +47 -0
  468. package/src/components/index.ts +2 -0
  469. package/src/components/instances.ts +18 -45
  470. package/src/components/sprite-instances.ts +1 -1
  471. package/src/construct-renderer.ts +1 -1
  472. package/src/device/gpu-residency.ts +26 -25
  473. package/src/dynamic-geometry.ts +12 -1
  474. package/src/errors/cloud.ts +103 -0
  475. package/src/errors/render.ts +47 -8
  476. package/src/examples/single-layer-medium-surface.ts +59 -0
  477. package/src/extract/camera.ts +15 -1
  478. package/src/extract/contracts.ts +5 -0
  479. package/src/extract/material-context.ts +21 -0
  480. package/src/features/barrel-distortion.ts +172 -0
  481. package/src/features/error-reporting.ts +26 -6
  482. package/src/features/host.ts +128 -19
  483. package/src/features/plan.ts +10 -0
  484. package/src/features/render-graph-contribution.ts +9 -0
  485. package/src/features/render-graph-raster.ts +45 -3
  486. package/src/features/targets.ts +66 -0
  487. package/src/features/types.ts +51 -0
  488. package/src/fullscreen-post-process-pass.ts +41 -9
  489. package/src/glyph-text-layout-system.ts +2 -2
  490. package/src/gpu-dirty-ranges.ts +48 -0
  491. package/src/gpu-driven/batch-topology.ts +53 -0
  492. package/src/gpu-driven/material-artifacts.ts +33 -25
  493. package/src/gpu-driven/prepared-draw.ts +12 -4
  494. package/src/gpu-driven/production-raster-material.ts +1894 -0
  495. package/src/gpu-driven/production-raster.ts +825 -784
  496. package/src/gpu-driven/resource-allocation.ts +142 -0
  497. package/src/gpu-driven/shadow-ownership.ts +71 -0
  498. package/src/gpu-driven/view-gpu.ts +164 -10
  499. package/src/gpu-scene.ts +75 -84
  500. package/src/hdrp-buffers.ts +4 -3
  501. package/src/ibl/frame-resources.ts +0 -1
  502. package/src/ibl/skylight-bind-group.ts +62 -32
  503. package/src/index.ts +205 -9
  504. package/src/inspection-types.ts +162 -0
  505. package/src/instance-buffer-cache.ts +4 -4
  506. package/src/instances.ts +152 -569
  507. package/src/pbr-pipeline.ts +230 -30
  508. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  509. package/src/pipeline/standard-forward-lane.ts +313 -57
  510. package/src/pipeline/standard-output/graph.ts +8 -2
  511. package/src/pipeline/standard-output/lut-gpu.ts +3 -3
  512. package/src/pipeline/standard-output/resources.ts +2 -2
  513. package/src/pipeline/standard-output/types.ts +12 -1
  514. package/src/pipeline/standard-pipeline.ts +291 -18
  515. package/src/pipeline/standard-post.ts +90 -24
  516. package/src/pipeline-builder.ts +1 -1
  517. package/src/plugin.ts +4 -0
  518. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  519. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  520. package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
  521. package/src/publication/__tests__/features.integration.test.ts +122 -0
  522. package/src/publication/__tests__/programs.unit.test.ts +25 -0
  523. package/src/publication/__tests__/publication.integration.test.ts +370 -0
  524. package/src/publication/__tests__/targets.integration.test.ts +120 -0
  525. package/src/publication/__tests__/video.browser.test.ts +50 -0
  526. package/src/publication/contract.ts +104 -0
  527. package/src/publication/dependencies.ts +54 -0
  528. package/src/publication/prepare-geometry.ts +94 -0
  529. package/src/publication/programs.ts +45 -0
  530. package/src/publication/publisher.ts +618 -0
  531. package/src/publication/receiver.ts +297 -0
  532. package/src/publication/resource-scope.ts +31 -0
  533. package/src/publication/targets.ts +182 -0
  534. package/src/publication/video.ts +33 -0
  535. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  536. package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
  537. package/src/record/__tests__/sprite-material-abi.unit.test.ts +9 -11
  538. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  539. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  540. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  541. package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
  542. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  543. package/src/record/barrel-distortion-frame.ts +110 -0
  544. package/src/record/dynamic-geometry-consumption.ts +39 -9
  545. package/src/record/fold-buckets.ts +855 -0
  546. package/src/record/fold-instance-buffer.ts +51 -0
  547. package/src/record/frame-lighting.ts +36 -2
  548. package/src/record/frame-snapshot.ts +45 -9
  549. package/src/record/frame.ts +258 -1105
  550. package/src/record/gpu-draw-receipts.ts +38 -0
  551. package/src/record/gpu-timing.ts +48 -5
  552. package/src/record/helpers.ts +2 -2
  553. package/src/record/main-pass-geometry.ts +272 -84
  554. package/src/record/main-pass-material.ts +102 -36
  555. package/src/record/main-pass-sprite-draws.ts +13 -217
  556. package/src/record/main-pass.ts +164 -27
  557. package/src/record/motion-blur-receipt.ts +91 -0
  558. package/src/record/prepared-material-bindings.ts +11 -6
  559. package/src/record/probe-blend-buffer.ts +180 -0
  560. package/src/record/recovery-pipeline.ts +35 -3
  561. package/src/record/render-context.ts +41 -5
  562. package/src/record/shadow-pass.ts +30 -4
  563. package/src/record/skybox-post-pass.ts +28 -4
  564. package/src/record/sprite-instance-buffer.ts +155 -0
  565. package/src/record/target-capture-graph.ts +258 -0
  566. package/src/record/typed-frame-graph.ts +776 -340
  567. package/src/record/view-ubo.ts +27 -4
  568. package/src/record/volume-params.ts +225 -0
  569. package/src/recovery/render-system-candidate.ts +243 -50
  570. package/src/reflection/record-owner.ts +7 -3
  571. package/src/render-contract.ts +54 -5
  572. package/src/render-graph-primitives.ts +7 -1
  573. package/src/render-pipeline.ts +130 -0
  574. package/src/render-system-extract-tail.ts +90 -78
  575. package/src/render-system-extract.ts +76 -76
  576. package/src/render-system-presentation.ts +56 -0
  577. package/src/render-system-producer-roots.ts +96 -0
  578. package/src/render-system-projections.ts +3 -2
  579. package/src/render-system-residency.ts +159 -0
  580. package/src/render-system.ts +421 -408
  581. package/src/scene/probe-blend.ts +96 -4
  582. package/src/scene/render-scene.ts +416 -337
  583. package/src/scene/render-source.ts +90 -0
  584. package/src/scene/source-systems.ts +33 -0
  585. package/src/ssao-buffers.ts +95 -2
  586. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  587. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  588. package/src/surface/dynamic-input.ts +658 -0
  589. package/src/surface/gpu-driven.ts +147 -0
  590. package/src/surface/submission-observation.ts +517 -0
  591. package/src/systems/skin-palette-allocator.ts +5 -1
  592. package/src/systems/skin-palette-types.ts +11 -0
  593. package/src/systems/transparent-dispatch.ts +2 -2
  594. package/src/systems/transparent-sort-config.ts +3 -1
  595. package/src/temporal/gpu.ts +101 -17
  596. package/src/temporal/inspection.ts +7 -1
  597. package/src/temporal/standard-scene-data.ts +5 -0
  598. package/src/temporal/target-coverage-attachment.ts +4 -0
  599. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  600. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  601. package/src/transmission/single-layer-medium.ts +322 -0
  602. package/src/typed-render-graph-primitives.ts +70 -2
  603. package/src/volume/component.ts +10 -9
  604. package/src/volume/extract.ts +11 -5
  605. package/src/volume/inspection.ts +3 -0
  606. package/src/volume/passes.ts +87 -4
  607. package/src/volume/resources.ts +2 -1
  608. package/dist/chunk-3RTCJTH4.mjs +0 -1610
  609. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  610. package/dist/chunk-BLXGONR2.mjs.map +0 -1
  611. package/dist/chunk-ILQ5MEZF.mjs +0 -32
  612. package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
  613. package/dist/chunk-LEAXOMYJ.mjs.map +0 -1
  614. package/dist/chunk-NB2S7ZRX.mjs +0 -1783
  615. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  616. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  617. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  618. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  619. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  620. package/dist/chunk-PLAXOOX5.mjs +0 -1907
  621. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  622. package/dist/chunk-RXZ3RGOU.mjs +0 -53
  623. package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
  624. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -6,7 +6,7 @@ import {
6
6
  DynamicTextureStore,
7
7
  } from '@forgeax/engine-assets-runtime';
8
8
  import { audioLoader } from '@forgeax/engine-audio-webaudio';
9
- import { Update, type World } from '@forgeax/engine-ecs';
9
+ import type { World } from '@forgeax/engine-ecs';
10
10
  import { createRenderReadLease, type RenderReadLease } from '@forgeax/engine-ecs/projection';
11
11
  import {
12
12
  DEFAULT_VERTEX_ATTRIBUTE_MAP,
@@ -14,7 +14,6 @@ import {
14
14
  } from '@forgeax/engine-geometry';
15
15
  import type {
16
16
  BindGroupLayout,
17
- Buffer,
18
17
  PipelineLayout,
19
18
  RenderPipeline,
20
19
  Result,
@@ -22,12 +21,14 @@ import type {
22
21
  RhiDevice,
23
22
  } from '@forgeax/engine-rhi';
24
23
  import { err, ok, RhiError, validateDrawArgs } from '@forgeax/engine-rhi';
25
- import { registerPropagateTransforms } from '@forgeax/engine-scene';
26
24
  import {
27
25
  findVariantByKey,
28
26
  type MaterialShaderEntry,
29
27
  type MaterialShaderManifestEntry,
30
28
  ShaderCatalog,
29
+ SINGLE_LAYER_MEDIUM_MSAA_PAIRED_COLOR_WGSL,
30
+ SINGLE_LAYER_MEDIUM_MSAA_RAW_DEPTH_WGSL,
31
+ SINGLE_LAYER_MEDIUM_RAW_DEPTH_WGSL,
31
32
  standardPhysicalTextureFields,
32
33
  } from '@forgeax/engine-shader';
33
34
  import type {
@@ -37,6 +38,11 @@ import type {
37
38
  PrimitiveTopology,
38
39
  VertexAttributeMap,
39
40
  } from '@forgeax/engine-types';
41
+ import { type PublishedRenderFrameInput, RenderPublicationError } from '../publication/contract';
42
+ import { installPublicationPrograms } from '../publication/programs';
43
+ import { type PreparedRenderPublication, RenderPublicationReceiver } from '../publication/receiver';
44
+ import { RenderPublicationTargetReceiver } from '../publication/targets';
45
+ import { registerRenderSourceSystems } from '../scene/source-systems';
40
46
  import { transmissionBackdropAvailable } from './device-feature-admission';
41
47
 
42
48
  export type { MaterialShaderManifestEntry } from '@forgeax/engine-shader';
@@ -53,6 +59,10 @@ import {
53
59
  RenderFeatureCapabilityMissingError,
54
60
  RenderFeatureStageFailedError,
55
61
  } from '../errors/render';
62
+ import {
63
+ BARREL_DISTORTION_FEATURE_IDENTITY,
64
+ createBarrelDistortionRenderFeature,
65
+ } from '../features/barrel-distortion';
56
66
  import {
57
67
  dofInspection,
58
68
  registerDepthOfFieldBuiltins,
@@ -65,7 +75,6 @@ import {
65
75
  type PostProcessShaderEntry,
66
76
  postProcessShaderModuleLabel,
67
77
  } from '../fullscreen-post-process-pass';
68
- import { glyphTextLayoutSystem } from '../glyph-text-layout-system';
69
78
  import { GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX } from '../gpu-stage';
70
79
  import { type BloomInspection, emptyBloomInspection } from '../inspection-types';
71
80
  import { DeviceScope } from '../lifecycle';
@@ -74,9 +83,13 @@ import {
74
83
  isCanonicalStandardPbrMaterialShader,
75
84
  isStandardPbrMaterialShader,
76
85
  type PipelineGroup2Contract,
77
- resolvePipelineGroup2Contract,
78
86
  SKIN_MATERIAL_SHADER_ID,
79
87
  } from '../pbr-pipeline';
88
+ import {
89
+ SINGLE_LAYER_MEDIUM_MSAA_PAIRED_COLOR_POST_PROCESS_ID,
90
+ SINGLE_LAYER_MEDIUM_MSAA_RAW_DEPTH_POST_PROCESS_ID,
91
+ SINGLE_LAYER_MEDIUM_RAW_DEPTH_POST_PROCESS_ID,
92
+ } from '../pipeline/single-layer-medium-passes';
80
93
  import { standardPipeline } from '../pipeline/standard-pipeline';
81
94
  import { DEFAULT_STANDARD_PROFILE } from '../pipeline/standard-profile';
82
95
  import { buildPipelineForMaterialShader } from '../pipeline-builder';
@@ -132,7 +145,7 @@ import type {
132
145
  SsrShaderSources,
133
146
  VolumetricFogShaderSources,
134
147
  } from '../render-contract';
135
- import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID } from '../render-contract';
148
+ import { FXAA_POST_PROCESS_ID, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID } from '../render-contract';
136
149
  import {
137
150
  attachGpuPassTimingSession,
138
151
  createRenderSystem,
@@ -145,11 +158,12 @@ import {
145
158
  import { createGpuPassTimingObservationStore, observeGpuPassTimingDisabled } from '../renderer.js';
146
159
  import { postSpawnResolveJoints } from '../scene-instances/post-spawn-resolve-joints';
147
160
  import type { RenderTarget } from '../targets/contracts';
148
- import { tilemapChunkExtractSystem } from '../tilemap-chunk-extract-system';
149
161
  import type { TypedFrameObservationCapture } from '../typed-render-graph-primitives';
150
162
  import { registerAnalyticFogPostProcess } from './analytic-fog-registration';
151
163
  import type { RhiBackendPack } from './backend-contract';
164
+ import { inspectBarrelDistortion } from './barrel-distortion-inspection';
152
165
  import type { BundlerOptions } from './bundler-contract';
166
+ import { rejectZeroCanvasSize } from './canvas-draw-guard';
153
167
  import { createRendererDynamicGeometryController } from './dynamic-geometry-host';
154
168
  import { registerFxaaPostProcess } from './fxaa-registration';
155
169
  import type { RendererAssemblyImplementation } from './host-contract';
@@ -157,6 +171,7 @@ import { observeLodOcclusionForReceipt } from './lod-observation';
157
171
  import {
158
172
  isEngineOwnedMaterialShader,
159
173
  resolveMaterialPipelineBindGroups,
174
+ resolveMaterialPipelineGroup2Contract,
160
175
  resolveMaterialPipelineShaderId,
161
176
  resolveMaterialPipelineVertexEntry,
162
177
  resolveRendererMaterialShaderArtifact,
@@ -169,6 +184,7 @@ import {
169
184
  type MaterialShaderBindingContract,
170
185
  makeShaderDeviceAdapter,
171
186
  normalizeMaterialShaderVariantSet,
187
+ prepareLowLimitMaterialShaderEntry,
172
188
  prepareMaterialShaders,
173
189
  resolveMaterialShaderBackendArtifactKey,
174
190
  resolveMaterialShaderBindingContract,
@@ -188,6 +204,7 @@ import {
188
204
  publishGeneration,
189
205
  } from './recovery/generation';
190
206
  import { createRendererRecovery, type RendererRecovery } from './recovery/renderer-recover';
207
+ import { collectRequiredFullscreenPostProcesses } from './render-feature-post-processes';
191
208
  import { createRenderTargetHost } from './render-target-host';
192
209
  import {
193
210
  freezeRenderProfile,
@@ -198,6 +215,7 @@ import { projectRendererFeatureInspection } from './renderer-feature-inspection'
198
215
  import {
199
216
  type ContinuationTerminator,
200
217
  createContinuationTerminator,
218
+ guardFrameCompletion,
201
219
  } from './renderer-frame-transaction';
202
220
  import {
203
221
  ensureContextConfigured,
@@ -205,7 +223,7 @@ import {
205
223
  rendererInitializationPipelineError,
206
224
  wrapDisposeError,
207
225
  } from './renderer-helpers';
208
- import { projectRendererOutputInspection } from './renderer-inspection';
226
+ import { projectRendererOutputInspectionFromSurface } from './renderer-inspection';
209
227
  import {
210
228
  createRecoveryContinuation,
211
229
  createRecoveryDeadline,
@@ -229,7 +247,10 @@ import {
229
247
  type WebGPURendererInternals,
230
248
  } from './webgpu-renderer-bootstrap';
231
249
  import type { WebGPUOutcome } from './webgpu-renderer-contract';
232
- import { disposeObservationCaptureSet } from './webgpu-renderer-observation';
250
+ import {
251
+ createRendererObservationCaptureOwner,
252
+ type ObservationCaptureRead,
253
+ } from './webgpu-renderer-observation-owner';
233
254
  import {
234
255
  isPreparedMaterialVertexLayout,
235
256
  PREPARED_INSTANCE_VERTEX_ATTRS,
@@ -257,6 +278,7 @@ export {
257
278
  selectNoColorPbrVariant,
258
279
  selectPipelineLayoutForVariant,
259
280
  shouldDeferMissingPreparedMaterialShader,
281
+ stripCloudShadowBindingsForLowLimit,
260
282
  } from './material-shader-policy';
261
283
  export {
262
284
  createMeshSsboGrowController,
@@ -283,7 +305,6 @@ export type { WebGPUOutcome, WebGPURendererInternals } from './webgpu-renderer-c
283
305
  export { disposeObservationCaptureSet } from './webgpu-renderer-observation';
284
306
 
285
307
  /** Bundler injection and the WebGPU renderer construction entry points. */
286
- let nextDerivedSystemId = 0;
287
308
  export async function tryCreateWebGPURenderer(
288
309
  canvas: HTMLCanvasElement | OffscreenCanvas,
289
310
  options: RendererOptions | undefined,
@@ -295,7 +316,12 @@ export async function tryCreateWebGPURenderer(
295
316
  async function makeWebGPURenderer(
296
317
  internals: WebGPURendererInternals,
297
318
  ): Promise<RendererAssemblyImplementation> {
319
+ let publicationTargets: RenderPublicationTargetReceiver | undefined;
298
320
  let disposed = false;
321
+ const publicationReceiver =
322
+ internals.options?.publicationSource === undefined
323
+ ? undefined
324
+ : new RenderPublicationReceiver(internals.options.publicationSource);
299
325
  const observeTiming = observeGpuPassTimingDisabled;
300
326
  const frameContinuations = new Set<ContinuationTerminator>();
301
327
  type RecoveryInspection = RenderInspection['recovery'];
@@ -333,7 +359,13 @@ async function makeWebGPURenderer(
333
359
  let renderTargetDevice = internals.device;
334
360
  let renderTargetGeneration = 0;
335
361
  let renderSystemForTargetPromotion: RenderSystem | undefined;
336
- const featureHostResult = createRenderFeatureHost(internals.options?.features ?? []);
362
+ const requestedFeatures = internals.options?.features ?? [];
363
+ const featureHostFeatures = requestedFeatures.some(
364
+ (f) => f.identity === BARREL_DISTORTION_FEATURE_IDENTITY,
365
+ )
366
+ ? requestedFeatures
367
+ : [...requestedFeatures, createBarrelDistortionRenderFeature()];
368
+ const featureHostResult = createRenderFeatureHost(featureHostFeatures);
337
369
  if (!featureHostResult.ok) throw featureHostResult.error;
338
370
  internals.featureHost = featureHostResult.value;
339
371
  let rendererRecovery: RendererRecovery | undefined;
@@ -466,27 +498,8 @@ async function makeWebGPURenderer(
466
498
  featureHostResult.value.features.flatMap((feature) => feature.requiredMaterialShaders ?? []),
467
499
  );
468
500
  let requiredMaterialShaders = Object.freeze([...requiredMaterialShaderSet]);
469
- const collectRequiredFullscreenPostProcesses = (
470
- features: readonly RenderFeature<unknown>[],
471
- ): readonly { readonly identity: string; readonly source: string }[] => {
472
- const entries = new Map<string, { readonly identity: string; readonly source: string }>();
473
- for (const feature of features) {
474
- for (const entry of feature.requiredFullscreenPostProcesses ?? []) {
475
- const existing = entries.get(entry.identity);
476
- if (existing !== undefined && existing.source !== entry.source) {
477
- throw new RhiError({
478
- code: 'internal-error',
479
- expected: `fullscreen identity '${entry.identity}' has one source across render features`,
480
- hint: 'rename the conflicting fullscreen identity or make its WGSL source identical',
481
- });
482
- }
483
- entries.set(entry.identity, entry);
484
- }
485
- }
486
- return Object.freeze([...entries.values()]);
487
- };
488
- let requiredFullscreenPostProcesses = collectRequiredFullscreenPostProcesses(
489
- featureHostResult.value.features,
501
+ let requiredFullscreenPostProcesses = Object.freeze(
502
+ collectRequiredFullscreenPostProcesses(featureHostResult.value.features),
490
503
  );
491
504
  // Lazy ShaderCatalog instance (plan-strategy section S-10 / D-R10 / OQ-5
492
505
  // close): constructed on first access; subsequent accesses return the
@@ -536,7 +549,7 @@ async function makeWebGPURenderer(
536
549
  feature: RenderFeature<unknown>,
537
550
  ): Promise<Result<void, RhiError>> => {
538
551
  for (const postProcess of feature.requiredFullscreenPostProcesses ?? []) {
539
- const label = postProcessShaderModuleLabel(postProcess.identity, postProcess.source);
552
+ const label = postProcessShaderModuleLabel(postProcess.source);
540
553
  const shaderResult = internals.pack.createShaderModule
541
554
  ? await internals.pack.createShaderModule(internals.device, {
542
555
  code: postProcess.source,
@@ -577,27 +590,7 @@ async function makeWebGPURenderer(
577
590
  }
578
591
  return state.shaderInstance;
579
592
  };
580
- // D-S9: AssetRegistry instance shared with RenderSystem. RenderSystem
581
- // looks up MeshFilter.assetHandle here per frame; buildReadyWebGPU step 3
582
- // uploads the registry's builtin mesh geometry to GPU buffers so the
583
- // RenderSystem can route MeshFilter.assetHandle to a real (vbo, ibo) pair.
584
- // feat-20260527 M1 / w1: ShaderCatalog is now eager-constructed and
585
- // constructor-injected into AssetRegistry (plan-strategy D-1). The
586
- // ShaderCatalogDevice adapter (shared between the catalog and per-MaterialShader
587
- // pipeline cache) is already available at this point.
588
593
  const shaderCatalog = getShader();
589
- // bug-20260601-hello-tonemap-material-register M1 (plan-strategy D-1):
590
- // All material-shader entries are now registered from the manifest
591
- // BEFORE the renderer is returned, so `register<MaterialAsset>` referencing
592
- // an engine shader succeeds without waiting for `renderer.initialization`.
593
- // Host-injected ImportTransport remains a constructor-only dependency.
594
- // feat-20260705-runtime-tier2-decomposition M1 / w10 (D-1 / D-2): the sole
595
- // production assembly point injects (a) the post-spawn hook
596
- // `postSpawnResolveJoints` (auto-wire Skin.joints; D-1) and the audio
597
- // catalog-entry loader. The latter stays at this assembly boundary so
598
- // assets-runtime remains independent of the concrete Web Audio backend.
599
- // videoLoader is wired internally from graphics-extras; the full registry has
600
- // 11 engine kinds. This is the only `new AssetRegistry(...)` call in the repo.
601
594
  const assets = new AssetRegistry(
602
595
  shaderCatalog,
603
596
  internals.importTransport,
@@ -728,7 +721,9 @@ async function makeWebGPURenderer(
728
721
  gpuStore.configureGpuDevice(
729
722
  internals.device,
730
723
  packShaderFactory,
731
- (world, pod) => {
724
+ (world, pod, source) => {
725
+ // The accepted equirect identity already owns this renderer-local GPU projection.
726
+ if ('resolveAsset' in world) return ok(source);
732
727
  const handle = world.allocSharedRef('EquirectAsset', pod);
733
728
  return ok(handle);
734
729
  },
@@ -1137,6 +1132,9 @@ async function makeWebGPURenderer(
1137
1132
  const lookup = getShader().findMaterialArtifact(materialShaderId);
1138
1133
  const source = lookup.ok ? lookup.value.source : '';
1139
1134
  const paramSchema = lookup.ok ? lookup.value.paramSchema : explicitParamSchema;
1135
+ const singleLayerMedium =
1136
+ materialShaderId === 'forgeax::single-layer-medium' ||
1137
+ (lookup.ok && lookup.value.receipt?.surface?.model === 'single-layer-medium');
1140
1138
  if (paramSchema === undefined) return null;
1141
1139
  const cacheKey = `${materialShaderId}:${layoutKind}:${clustered}`;
1142
1140
  const cached = cacheState.perShaderMaterialLayoutCache.get(cacheKey);
@@ -1155,7 +1153,12 @@ async function makeWebGPURenderer(
1155
1153
  isStandardPbrMaterialShader(materialShaderId) ||
1156
1154
  standardPhysicalTextureFields(paramSchema).length > 0;
1157
1155
  const isStandardMapLayout = requiresStandardMapLayout;
1158
- if (!clustered && !isStandardMapLayout && isSharedMaterialUserRegionCompatible(paramSchema)) {
1156
+ if (
1157
+ !clustered &&
1158
+ !singleLayerMedium &&
1159
+ !isStandardMapLayout &&
1160
+ isSharedMaterialUserRegionCompatible(paramSchema)
1161
+ ) {
1159
1162
  cacheState.perShaderMaterialLayoutCache.set(cacheKey, {
1160
1163
  source,
1161
1164
  paramSchema,
@@ -1165,7 +1168,11 @@ async function makeWebGPURenderer(
1165
1168
  return null;
1166
1169
  }
1167
1170
  const spec: PipelineSpec = {
1168
- shader: { id: materialShaderId, passKind: 'forward', variantSet: undefined },
1171
+ shader: {
1172
+ id: singleLayerMedium ? 'forgeax::single-layer-medium' : materialShaderId,
1173
+ passKind: 'forward',
1174
+ variantSet: undefined,
1175
+ },
1169
1176
  attachments: { colorFormats: [], depthFormat: undefined, sampleCount: 1 },
1170
1177
  geometry: { topology: 'triangle-list', vertexLayout: {} },
1171
1178
  renderState: undefined,
@@ -1552,7 +1559,11 @@ async function makeWebGPURenderer(
1552
1559
  : getShaderModuleAdapter(),
1553
1560
  pipelineLayout,
1554
1561
  vertexBuffers,
1555
- ...(layoutKind === 'pbr-skin' || layoutKind === 'gpu-driven-skin' ? { layoutKind } : {}),
1562
+ ...(layoutKind === 'pbr-skin' ||
1563
+ layoutKind === 'gpu-driven-skin' ||
1564
+ layoutKind === 'gpu-driven-cluster-skin'
1565
+ ? { layoutKind }
1566
+ : {}),
1556
1567
  };
1557
1568
  };
1558
1569
  /**
@@ -1619,7 +1630,10 @@ async function makeWebGPURenderer(
1619
1630
  particleInputLanes?: number,
1620
1631
  coverageOnly = false,
1621
1632
  ): RenderPipeline | null => {
1622
- const declaredGroup2Contract = resolvePipelineGroup2Contract(entry.source);
1633
+ const declaredGroup2Contract = resolveMaterialPipelineGroup2Contract(
1634
+ entry.source,
1635
+ layoutKindOverride,
1636
+ );
1623
1637
  const group2Contract =
1624
1638
  declaredGroup2Contract === 'mesh' &&
1625
1639
  (materialShaderId === 'forgeax::vfx-render.particles.mesh' ||
@@ -2048,6 +2062,10 @@ async function makeWebGPURenderer(
2048
2062
  }
2049
2063
  }
2050
2064
  }
2065
+ shaderEntry = prepareLowLimitMaterialShaderEntry(
2066
+ shaderEntry,
2067
+ currentBuildDevice().limits.maxSampledTexturesPerShaderStage,
2068
+ );
2051
2069
  // feat-20260609 M4 / R3-fixup: append `-${passKind}` to the PSO label so
2052
2070
  // GPU debug captures (and the shadow-caster branch in the builder)
2053
2071
  // make the cache variant visible. The fallback path above keeps the
@@ -2115,10 +2133,50 @@ async function makeWebGPURenderer(
2115
2133
  ) => {
2116
2134
  const pipeline = getMaterialShaderPipeline(...args);
2117
2135
  if (pipeline === null) return null;
2136
+ const materialShaderId = args[0];
2137
+ const variantSet = args[5];
2138
+ const passKind = args[6] ?? 'forward';
2139
+ const vertexLayoutProjection = args[13];
2140
+ const layoutKind = args[15];
2141
+ const sceneIndexAddress =
2142
+ layoutKind === 'gpu-driven-pbr' ||
2143
+ layoutKind === 'gpu-driven-skin' ||
2144
+ layoutKind === 'gpu-driven-cluster-pbr' ||
2145
+ layoutKind === 'gpu-driven-cluster-skin';
2146
+ const artifact = resolveRendererMaterialShaderArtifact(
2147
+ materialShaderId,
2148
+ getShader(),
2149
+ pipelineState?.gpuDrivenPbrPrograms,
2150
+ {
2151
+ ...(vertexLayoutProjection === undefined
2152
+ ? {}
2153
+ : {
2154
+ vertexColorAvailable: vertexLayoutProjection.attributes.some(
2155
+ (attribute) => attribute.key === 'color',
2156
+ ),
2157
+ }),
2158
+ ...(layoutKind === 'pbr-skin' ||
2159
+ layoutKind === 'gpu-driven-skin' ||
2160
+ layoutKind === 'gpu-driven-cluster-skin'
2161
+ ? { deformation: 'skin' as const }
2162
+ : {}),
2163
+ ...(variantSet === undefined ? {} : { variantSet }),
2164
+ address: sceneIndexAddress ? 'scene-index' : 'direct',
2165
+ pass: passKind === 'shadow-caster' ? 'shadow' : 'forward',
2166
+ },
2167
+ );
2118
2168
  return {
2119
2169
  pipeline,
2120
2170
  group2Contract:
2121
2171
  materialShaderPipelineGroup2Contracts.get(pipeline as object) ?? ('mesh' as const),
2172
+ ...(artifact?.receipt === undefined
2173
+ ? {}
2174
+ : {
2175
+ receipt: {
2176
+ identity: artifact.receipt.receiptIdentity,
2177
+ generation: artifact.receipt.generation,
2178
+ },
2179
+ }),
2122
2180
  };
2123
2181
  };
2124
2182
  const getParamSchema = (materialShaderId: string) => {
@@ -2172,10 +2230,11 @@ async function makeWebGPURenderer(
2172
2230
  colorFormats: readonly GPUTextureFormat[],
2173
2231
  label: string,
2174
2232
  ): RenderPipeline | null => {
2233
+ const isFxaaPipeline = label.startsWith(`post-process-${FXAA_POST_PROCESS_ID}-pso-`);
2175
2234
  const moduleFactory = getShaderModuleAdapter();
2176
2235
  const moduleResult = moduleFactory.createShaderModule({
2177
2236
  code: entry.source,
2178
- label: `${label}-module`,
2237
+ label: postProcessShaderModuleLabel(entry.source),
2179
2238
  });
2180
2239
  if (!moduleResult.ok) {
2181
2240
  // 'rhi-not-available' = async compile in flight: caller falls back one frame.
@@ -2186,7 +2245,7 @@ async function makeWebGPURenderer(
2186
2245
  }
2187
2246
  return null;
2188
2247
  }
2189
- if (currentEmptyPostProcessBgl() === null) {
2248
+ if (!isFxaaPipeline && entry.usesView !== true && currentEmptyPostProcessBgl() === null) {
2190
2249
  const bglRes = currentBuildDevice().createBindGroupLayout({ entries: [] });
2191
2250
  if (!bglRes.ok) {
2192
2251
  internals.errorRegistry.fire(bglRes.error);
@@ -2199,9 +2258,18 @@ async function makeWebGPURenderer(
2199
2258
  emptyPostProcessBgl = bglRes.value;
2200
2259
  }
2201
2260
  }
2261
+ const viewLayout =
2262
+ entry.usesView === true ? currentPipelineState()?.viewBindGroupLayout : undefined;
2263
+ const group0Layout = viewLayout ?? currentEmptyPostProcessBgl();
2264
+ if (group0Layout === null || group0Layout === undefined) {
2265
+ internals.errorRegistry.fire(
2266
+ new Error('fullscreen post-process View layout is unavailable') as never,
2267
+ );
2268
+ return null;
2269
+ }
2202
2270
  const layoutRes = currentBuildDevice().createPipelineLayout({
2203
2271
  label: `${label}-layout`,
2204
- bindGroupLayouts: [currentEmptyPostProcessBgl() as BindGroupLayout, bgl],
2272
+ bindGroupLayouts: isFxaaPipeline ? [bgl] : [group0Layout as BindGroupLayout, bgl],
2205
2273
  });
2206
2274
  if (!layoutRes.ok) {
2207
2275
  internals.errorRegistry.fire(layoutRes.error);
@@ -2439,6 +2507,22 @@ async function makeWebGPURenderer(
2439
2507
  });
2440
2508
  attachGpuPassTimingSession(internals, gpuPassTimingSession);
2441
2509
  renderSystemForTargetPromotion = renderSystem;
2510
+ renderSystem.registerBuiltinPostProcess(SINGLE_LAYER_MEDIUM_RAW_DEPTH_POST_PROCESS_ID, {
2511
+ source: SINGLE_LAYER_MEDIUM_RAW_DEPTH_WGSL,
2512
+ reads: ['input', { key: 'scene-depth', sampleType: 'depth' }],
2513
+ });
2514
+ const pairedMsaaReads = [
2515
+ { key: 'input', sampleType: 'multisampled-float' as const },
2516
+ { key: 'scene-depth', sampleType: 'depth' as const },
2517
+ ];
2518
+ renderSystem.registerBuiltinPostProcess(SINGLE_LAYER_MEDIUM_MSAA_PAIRED_COLOR_POST_PROCESS_ID, {
2519
+ source: SINGLE_LAYER_MEDIUM_MSAA_PAIRED_COLOR_WGSL,
2520
+ reads: pairedMsaaReads,
2521
+ });
2522
+ renderSystem.registerBuiltinPostProcess(SINGLE_LAYER_MEDIUM_MSAA_RAW_DEPTH_POST_PROCESS_ID, {
2523
+ source: SINGLE_LAYER_MEDIUM_MSAA_RAW_DEPTH_WGSL,
2524
+ reads: pairedMsaaReads,
2525
+ });
2442
2526
  if (
2443
2527
  internals.device.caps.backendKind === 'null' &&
2444
2528
  Array.from(getShader().entries()).length === 0
@@ -2466,7 +2550,6 @@ async function makeWebGPURenderer(
2466
2550
  currentGeneration: () => activeDeviceScope.generation,
2467
2551
  renderSystem,
2468
2552
  });
2469
- const derivedSystemNames = new Map<World, string>();
2470
2553
  const transformReleases = new Map<World, () => void>();
2471
2554
  const attachmentOwner = {};
2472
2555
  let frameId = 0;
@@ -2475,184 +2558,41 @@ async function makeWebGPURenderer(
2475
2558
  const receiptTimings = new WeakMap<FrameReceipt, Promise<VolumeTimingObservation>>();
2476
2559
  let latestReceipt: FrameReceipt | undefined;
2477
2560
  let pendingObservationDomains: readonly FrameObservationDomain[] | undefined;
2478
- let observationAllocationCount = 0;
2479
- let observationLiveCount = 0;
2480
- let observationPeakLiveCount = 0;
2481
- let observationMapCount = 0;
2482
- let observationReadbackCount = 0;
2483
- let observationLiveByteLength = 0;
2484
- const observationCaptureOwner = (() => {
2485
- const capturesByFrame = new Map<number, TypedFrameObservationCapture[]>();
2486
- return {
2487
- register(capture: TypedFrameObservationCapture): void {
2488
- const captures = capturesByFrame.get(capture.frameNumber) ?? [];
2489
- captures.push(capture);
2490
- capturesByFrame.set(capture.frameNumber, captures);
2491
- observationAllocationCount += 1;
2492
- observationLiveCount += 1;
2493
- observationPeakLiveCount = Math.max(observationPeakLiveCount, observationLiveCount);
2494
- observationLiveByteLength += capture.bytesPerRow * capture.height;
2495
- },
2496
- consume(frameNumber: number): readonly TypedFrameObservationCapture[] {
2497
- const captures = capturesByFrame.get(frameNumber) ?? [];
2498
- capturesByFrame.delete(frameNumber);
2499
- return Object.freeze(captures);
2500
- },
2501
- drain(): readonly TypedFrameObservationCapture[] {
2502
- const captures = [...capturesByFrame.values()].flat();
2503
- capturesByFrame.clear();
2504
- return Object.freeze(captures);
2505
- },
2506
- };
2507
- })();
2561
+ const observationOwner = createRendererObservationCaptureOwner((error) => {
2562
+ internals.errorRegistry.fire(error);
2563
+ });
2564
+ const {
2565
+ observationCaptureOwner,
2566
+ stats: observationStats,
2567
+ receiptObservationCaptures,
2568
+ receiptObservationBuffers,
2569
+ destroyedObservationBuffers,
2570
+ disposeObservationCaptures,
2571
+ disposeOwnedObservationCaptures,
2572
+ readObservationCapture,
2573
+ disposeReceiptObservationCaptures,
2574
+ } = observationOwner;
2508
2575
  Object.assign(internals, { observationCaptureOwner });
2509
- let expectedObservationGraphGeneration: number | undefined;
2510
2576
  Object.defineProperty(internals, 'observationGraphGeneration', {
2511
2577
  configurable: true,
2512
- get: () => expectedObservationGraphGeneration,
2578
+ get: () => observationOwner.expectedGraphGeneration,
2513
2579
  set: (generation: number | undefined) => {
2514
- expectedObservationGraphGeneration = generation;
2580
+ observationOwner.expectedGraphGeneration = generation;
2515
2581
  },
2516
2582
  });
2517
- type ObservationCaptureRead = () => Promise<
2518
- RenderResult<
2519
- readonly {
2520
- readonly capture: TypedFrameObservationCapture;
2521
- readonly bytes: Uint8Array;
2522
- }[],
2523
- RenderError
2524
- >
2525
- >;
2526
- const receiptObservationCaptures = new Map<FrameReceipt, ObservationCaptureRead>();
2527
- const receiptObservationBuffers = new Map<
2528
- FrameReceipt,
2529
- readonly TypedFrameObservationCapture[]
2530
- >();
2531
- const destroyedObservationBuffers = new WeakSet<Buffer>();
2532
- const observationBufferCleanupFailures = new WeakMap<Buffer, RendererContractFailureError>();
2533
- const failedObservationCaptures = new Map<Buffer, TypedFrameObservationCapture>();
2534
- const disposeObservationCaptures = (
2535
- captures: readonly TypedFrameObservationCapture[],
2536
- ): RendererContractFailureError | undefined => {
2537
- const wasDestroyed = new Set(
2538
- captures
2539
- .filter((capture) => destroyedObservationBuffers.has(capture.buffer))
2540
- .map((capture) => capture.buffer),
2541
- );
2542
- const result = disposeObservationCaptureSet(
2543
- captures,
2544
- destroyedObservationBuffers,
2545
- observationBufferCleanupFailures,
2546
- (failure) => internals.errorRegistry.fire(failure),
2547
- );
2548
- for (const capture of captures) {
2549
- if (!wasDestroyed.has(capture.buffer) && destroyedObservationBuffers.has(capture.buffer)) {
2550
- observationLiveCount = Math.max(0, observationLiveCount - 1);
2551
- observationLiveByteLength = Math.max(
2552
- 0,
2553
- observationLiveByteLength - capture.bytesPerRow * capture.height,
2554
- );
2555
- }
2556
- }
2557
- return result;
2558
- };
2559
- const disposeOwnedObservationCaptures = (
2560
- captures: readonly TypedFrameObservationCapture[],
2561
- ): RendererContractFailureError | undefined => {
2562
- const failure = disposeObservationCaptures(captures);
2563
- if (failure !== undefined) {
2564
- for (const capture of captures) {
2565
- if (!destroyedObservationBuffers.has(capture.buffer)) {
2566
- failedObservationCaptures.set(capture.buffer, capture);
2567
- }
2568
- }
2569
- }
2570
- return failure;
2571
- };
2572
- const readObservationCapture = async (
2573
- capture: TypedFrameObservationCapture,
2574
- ): Promise<RenderResult<Uint8Array, RenderError>> => {
2575
- try {
2576
- if (typeof capture.buffer.mapAsync !== 'function') {
2577
- const cleanupFailure = disposeObservationCaptures([capture]);
2578
- return err(
2579
- cleanupFailure ??
2580
- new RendererContractFailureError(
2581
- 'observe',
2582
- `the ${capture.domain} receipt-bound readback backend has no mapAsync capability`,
2583
- ),
2584
- );
2585
- }
2586
- observationMapCount += 1;
2587
- const mapped = await capture.buffer.mapAsync(1);
2588
- if (!mapped.ok) {
2589
- const cleanupFailure = disposeObservationCaptures([capture]);
2590
- return err(
2591
- cleanupFailure ??
2592
- new RendererContractFailureError(
2593
- 'observe',
2594
- `mapping ${capture.domain} receipt-bound readback failed: ${mapped.error.code}`,
2595
- ),
2596
- );
2597
- }
2598
- const range = mapped.value.getMappedRange();
2599
- if (!range.ok) {
2600
- mapped.value.unmap();
2601
- const cleanupFailure = disposeObservationCaptures([capture]);
2602
- return err(
2603
- cleanupFailure ??
2604
- new RendererContractFailureError(
2605
- 'observe',
2606
- `reading ${capture.domain} receipt-bound readback failed: ${range.error.code}`,
2607
- ),
2608
- );
2609
- }
2610
- const bytes = new Uint8Array(range.value.slice(0));
2611
- mapped.value.unmap();
2612
- observationReadbackCount += 1;
2613
- const cleanupFailure = disposeObservationCaptures([capture]);
2614
- if (cleanupFailure !== undefined) return err(cleanupFailure);
2615
- return ok(bytes);
2616
- } catch (cause) {
2617
- const cleanupFailure = disposeObservationCaptures([capture]);
2618
- return err(
2619
- cleanupFailure ??
2620
- new RendererContractFailureError(
2621
- 'observe',
2622
- `reading ${capture.domain} receipt-bound readback threw: ${
2623
- cause instanceof Error ? cause.message : String(cause)
2624
- }`,
2625
- ),
2626
- );
2627
- }
2628
- };
2629
-
2630
- const disposeReceiptObservationCaptures = (): RendererContractFailureError | undefined => {
2631
- let firstFailure: RendererContractFailureError | undefined;
2632
- for (const [receipt, captures] of receiptObservationBuffers) {
2633
- const failure = disposeObservationCaptures(captures);
2634
- firstFailure ??= failure;
2635
- if (captures.every((capture) => destroyedObservationBuffers.has(capture.buffer))) {
2636
- receiptObservationBuffers.delete(receipt);
2637
- }
2638
- }
2639
- receiptObservationCaptures.clear();
2640
- const retryCaptures = [...failedObservationCaptures.values()];
2641
- const retryFailure = disposeObservationCaptures(retryCaptures);
2642
- firstFailure ??= retryFailure;
2643
- for (const capture of retryCaptures) {
2644
- if (destroyedObservationBuffers.has(capture.buffer)) {
2645
- failedObservationCaptures.delete(capture.buffer);
2646
- }
2647
- }
2648
- const ownedFailure = disposeOwnedObservationCaptures(observationCaptureOwner.drain());
2649
- firstFailure ??= ownedFailure;
2650
- return firstFailure;
2651
- };
2652
2583
  let surfaceReleased = false;
2653
2584
  const renderer: RendererAssemblyImplementation = {
2654
- instances: renderSystem.instances,
2585
+ setSurfaceDynamicInput(frame) {
2586
+ renderSystem.setSurfaceDynamicInput(frame);
2587
+ },
2655
2588
  attach(world: World): RenderResult<RenderWorldLease, RenderError> {
2589
+ if (publicationReceiver !== undefined)
2590
+ return err(
2591
+ new RenderPublicationError({
2592
+ reason: 'identity',
2593
+ subject: 'publication Renderer has no World attachment',
2594
+ }),
2595
+ );
2656
2596
  const attached = this.attachScene(world);
2657
2597
  if (!attached.ok) {
2658
2598
  return err(new RendererContractFailureError('attach', attached.error.hint));
@@ -2714,25 +2654,29 @@ async function makeWebGPURenderer(
2714
2654
  ? 'faulted'
2715
2655
  : 'alive';
2716
2656
  const graph = deviceLost ? undefined : renderSystem.perFrameGraphInfo;
2657
+ const graphResourceAllocation = graph?.resourceAllocation;
2658
+ const graphGenerationAllocation = deviceLost
2659
+ ? undefined
2660
+ : renderSystem.renderGraphGenerationAllocation;
2717
2661
  const standardLighting = deviceLost ? undefined : renderSystem.standardLightingInspection;
2662
+ const barrelDistortion = inspectBarrelDistortion(
2663
+ disposed,
2664
+ deviceLost,
2665
+ surfaceReleased,
2666
+ frameId,
2667
+ activeDeviceScope.generation,
2668
+ renderSystem.barrelDistortionInspection,
2669
+ );
2718
2670
  const bloom: BloomInspection = deviceLost ? emptyBloomInspection() : renderSystem.bloom;
2719
- const surfaceStorage = pipelineState?.format ?? 'rgba8unorm';
2720
- const surfaceDisplay = pipelineState?.colorAttachmentFormat ?? 'rgba8unorm';
2721
2671
  const observationId = `${STANDARD_OUTPUT_TRANSFORM_FEATURE_ID}:frame-${frameId}`;
2722
- const outputInspection = projectRendererOutputInspection({
2672
+ const outputInspection = projectRendererOutputInspectionFromSurface({
2723
2673
  graph,
2724
- surfaceAvailable: !surfaceReleased && pipelineState !== null,
2725
- surfaceStorage,
2726
- surfaceDisplay,
2727
- ...(pipelineState?.surfaceProfile === undefined
2728
- ? {}
2729
- : { surfaceProfile: pipelineState.surfaceProfile }),
2674
+ surfaceReleased,
2675
+ pipelineState,
2730
2676
  rgba16floatRenderable: internals.device.caps.rgba16floatRenderable,
2731
2677
  autoExposure: renderSystem.autoExposure,
2732
2678
  standardLut: renderSystem.standardLut,
2733
- ...(internals.context?.presentationProof === undefined
2734
- ? {}
2735
- : { presentationProof: internals.context.presentationProof }),
2679
+ presentationProof: internals.context?.presentationProof,
2736
2680
  });
2737
2681
  const volumetricFog = renderSystem.volumetricFog;
2738
2682
  const directionalShadow = renderSystem.directionalShadow;
@@ -2747,6 +2691,7 @@ async function makeWebGPURenderer(
2747
2691
  frameId,
2748
2692
  deviceGeneration: activeDeviceScope.generation,
2749
2693
  }),
2694
+ barrelDistortion,
2750
2695
  ...projectRendererFeatureInspection(internals.featureHost),
2751
2696
  featureGraph: renderSystem.featureGraphInspection,
2752
2697
  materialTextureSources: renderSystem.materialTextureSources,
@@ -2756,9 +2701,6 @@ async function makeWebGPURenderer(
2756
2701
  renderSystem.instanceCollectionsInspection.map((collection) =>
2757
2702
  Object.freeze({
2758
2703
  ...collection,
2759
- dirtyRanges: Object.freeze(
2760
- collection.dirtyRanges.map((range) => Object.freeze({ ...range })),
2761
- ),
2762
2704
  uploadRanges: Object.freeze(
2763
2705
  collection.uploadRanges.map((range) => Object.freeze({ ...range })),
2764
2706
  ),
@@ -2775,6 +2717,12 @@ async function makeWebGPURenderer(
2775
2717
  ),
2776
2718
  dynamicGeometry: dynamicGeometry.inspect(),
2777
2719
  renderScene: renderSystem.renderScene,
2720
+ ...(graphResourceAllocation === undefined
2721
+ ? {}
2722
+ : { renderGraphResourceAllocation: graphResourceAllocation }),
2723
+ ...(graphGenerationAllocation === undefined
2724
+ ? {}
2725
+ : { renderGraphGenerationAllocation: graphGenerationAllocation }),
2778
2726
  ...(renderSystem.iblBinding === undefined ? {} : { iblBinding: renderSystem.iblBinding }),
2779
2727
  reflectionProbes: renderSystem.reflectionProbes,
2780
2728
  ssrDependencies: renderSystem.ssrDependencies,
@@ -2855,12 +2803,12 @@ async function makeWebGPURenderer(
2855
2803
  ? {}
2856
2804
  : { standardOutputColor: Object.freeze({ ...outputInspection.standardOutputColor }) }),
2857
2805
  resourceStats: Object.freeze({
2858
- allocationCount: observationAllocationCount,
2859
- liveCount: observationLiveCount,
2860
- peakLiveCount: observationPeakLiveCount,
2861
- mapCount: observationMapCount,
2862
- readbackCount: observationReadbackCount,
2863
- liveByteLength: observationLiveByteLength,
2806
+ allocationCount: observationStats.allocationCount,
2807
+ liveCount: observationStats.liveCount,
2808
+ peakLiveCount: observationStats.peakLiveCount,
2809
+ mapCount: observationStats.mapCount,
2810
+ readbackCount: observationStats.readbackCount,
2811
+ liveByteLength: observationStats.liveByteLength,
2864
2812
  }),
2865
2813
  }),
2866
2814
  });
@@ -2896,23 +2844,7 @@ async function makeWebGPURenderer(
2896
2844
  }
2897
2845
  if (attachedWorlds.has(world)) return ok(undefined);
2898
2846
  try {
2899
- const releaseTransforms = registerPropagateTransforms(world);
2900
- const derivedSystemName = `renderDerived:${++nextDerivedSystemId}`;
2901
- const derived = world.addSystem(Update, {
2902
- name: derivedSystemName,
2903
- queries: [],
2904
- fn: (world) => {
2905
- tilemapChunkExtractSystem(world, (guid) => assets.lookup(guid));
2906
- const glyphResult = glyphTextLayoutSystem(world, gpuStore);
2907
- if (!glyphResult.ok) throw glyphResult.error;
2908
- },
2909
- });
2910
- if (!derived.ok) {
2911
- releaseTransforms();
2912
- throw new Error(`failed to register ${derivedSystemName}: ${derived.error.code}`);
2913
- }
2914
- transformReleases.set(world, releaseTransforms);
2915
- derivedSystemNames.set(world, derivedSystemName);
2847
+ transformReleases.set(world, registerRenderSourceSystems(world, assets, gpuStore));
2916
2848
  attachedWorlds.add(world);
2917
2849
  return ok(undefined);
2918
2850
  } catch (cause) {
@@ -2943,11 +2875,6 @@ async function makeWebGPURenderer(
2943
2875
  }
2944
2876
  }
2945
2877
  renderSystem.detachScene(world);
2946
- const derivedSystemName = derivedSystemNames.get(world);
2947
- if (derivedSystemName !== undefined) {
2948
- world.removeSystem(Update, derivedSystemName);
2949
- derivedSystemNames.delete(world);
2950
- }
2951
2878
  transformReleases.get(world)?.();
2952
2879
  transformReleases.delete(world);
2953
2880
  },
@@ -3151,17 +3078,43 @@ async function makeWebGPURenderer(
3151
3078
  : ok(result.value);
3152
3079
  },
3153
3080
  draw(
3154
- worldsOrRequest: readonly World[] | RenderFrameInput,
3081
+ worldsOrRequest: readonly World[] | RenderFrameInput | PublishedRenderFrameInput,
3155
3082
  options?: DrawOwnerOptions,
3156
3083
  ): Result<void | FrameReceipt, RhiError | RenderError> {
3157
3084
  const isFrameRequest = !Array.isArray(worldsOrRequest);
3158
- const frameRequest = isFrameRequest ? (worldsOrRequest as RenderFrameInput) : undefined;
3085
+ const publicationRequest =
3086
+ isFrameRequest && 'publication' in worldsOrRequest
3087
+ ? (worldsOrRequest as PublishedRenderFrameInput)
3088
+ : undefined;
3089
+ const frameRequest =
3090
+ isFrameRequest && publicationRequest === undefined
3091
+ ? (worldsOrRequest as RenderFrameInput)
3092
+ : undefined;
3093
+ let publication: PreparedRenderPublication | undefined;
3094
+ if (publicationRequest !== undefined) {
3095
+ if (publicationReceiver === undefined)
3096
+ return err(
3097
+ new RenderPublicationError({
3098
+ reason: 'identity',
3099
+ subject: 'RendererOptions.publicationSource',
3100
+ }),
3101
+ );
3102
+ } else if (publicationReceiver !== undefined) {
3103
+ return err(
3104
+ new RenderPublicationError({
3105
+ reason: 'identity',
3106
+ subject: 'a publication-bound renderer cannot consume local World leases',
3107
+ }),
3108
+ );
3109
+ }
3159
3110
  const worlds: readonly World[] =
3160
3111
  frameRequest !== undefined
3161
3112
  ? frameRequest.leases
3162
3113
  .map((lease) => attachedLeases.get(lease))
3163
3114
  .filter((world): world is World => world !== undefined)
3164
- : (worldsOrRequest as readonly World[]);
3115
+ : publicationRequest === undefined
3116
+ ? (worldsOrRequest as readonly World[])
3117
+ : [];
3165
3118
  const readLeases: readonly RenderReadLease[] | undefined =
3166
3119
  frameRequest !== undefined
3167
3120
  ? frameRequest.leases
@@ -3212,8 +3165,18 @@ async function makeWebGPURenderer(
3212
3165
  ...(frameRequest.profileFrame === undefined
3213
3166
  ? {}
3214
3167
  : { profileFrame: frameRequest.profileFrame }),
3168
+ ...(frameRequest.geometryLane === undefined
3169
+ ? {}
3170
+ : { geometryLane: frameRequest.geometryLane }),
3215
3171
  }
3216
- : (options ?? { cameraOwner: 0, resourceOwner: 0 });
3172
+ : publicationRequest === undefined
3173
+ ? (options ?? { cameraOwner: 0, resourceOwner: 0 })
3174
+ : {
3175
+ cameraOwner: 0,
3176
+ resourceOwner: 0,
3177
+ sampleTimeSeconds: publicationRequest.publication.sampleTimeSeconds,
3178
+ temporalReset: publicationRequest.publication.temporalReset,
3179
+ };
3217
3180
  // feat-20260612-rhi-destroy-renderer-dispose-gpu-lifecycle / M5 / w21
3218
3181
  // (plan-strategy D-1, D-8): post-dispose the renderer is dead. AI
3219
3182
  // users observing `result.ok === false && err.code === 'rhi-not-
@@ -3239,6 +3202,8 @@ async function makeWebGPURenderer(
3239
3202
  }),
3240
3203
  );
3241
3204
  }
3205
+ const canvasSizeError = rejectZeroCanvasSize(internals.canvas.width, internals.canvas.height);
3206
+ if (canvasSizeError !== undefined) return err(canvasSizeError);
3242
3207
  // M2 / w9 (A-IN-5): device-lost guard — draw() silently returns err
3243
3208
  // without firing onError each frame. The device-lost channel fires once
3244
3209
  // through the dual-channel fan-out (:750-797); draw() does not repeat it
@@ -3287,7 +3252,8 @@ async function makeWebGPURenderer(
3287
3252
  // are non-exclusive: an empty array short-circuits to empty-worlds. The
3288
3253
  // check is defensive against JS callers passing a non-array despite the
3289
3254
  // compile-time World[] type (red-window migration safety).
3290
- const worldCount = Array.isArray(worlds) ? worlds.length : 0;
3255
+ const worldCount =
3256
+ publicationRequest === undefined ? (Array.isArray(worlds) ? worlds.length : 0) : 1;
3291
3257
  if (worldCount === 0 && internals.device.caps.backendKind === 'null') {
3292
3258
  return ok(undefined);
3293
3259
  }
@@ -3309,12 +3275,27 @@ async function makeWebGPURenderer(
3309
3275
  internals.errorRegistry,
3310
3276
  );
3311
3277
  if (!contextConfigured.ok) return contextConfigured;
3312
- renderTargetHost.beginFrame();
3313
3278
  // w24 — facade-level try/catch produces Result.err on unexpected throw
3314
3279
  // (D-P6 dual-channel preserved: per-stage RhiError continues to fan out
3315
3280
  // through onError separately; the facade Result is the synchronous
3316
3281
  // summary AI users can ignore or branch on).
3317
3282
  try {
3283
+ if (publicationRequest !== undefined && publicationReceiver !== undefined) {
3284
+ const accepted = publicationReceiver.accept(publicationRequest.publication);
3285
+ if (!accepted.ok) return accepted;
3286
+ publicationTargets ??= new RenderPublicationTargetReceiver(renderTargetHost);
3287
+ publication = {
3288
+ ...publicationTargets.apply(accepted.value),
3289
+ ...(publicationRequest.onFeatureSourceSubmitted === undefined
3290
+ ? {}
3291
+ : {
3292
+ onFeatureSourceSubmitted: publicationRequest.onFeatureSourceSubmitted,
3293
+ }),
3294
+ };
3295
+ installPublicationPrograms(assets, publicationRequest.publication.programs);
3296
+ }
3297
+ renderTargetHost.beginFrame();
3298
+
3318
3299
  const timingHost = internals as WebGPURendererInternals & {
3319
3300
  gpuPassTimingFrameIdentity?:
3320
3301
  | {
@@ -3352,7 +3333,13 @@ async function makeWebGPURenderer(
3352
3333
  graphGeneration: 0,
3353
3334
  };
3354
3335
  }
3355
- const submitted = renderSystem.draw(worlds, drawOptions, readLeases, volumeTimingCapture);
3336
+ const submitted = renderSystem.draw(
3337
+ worlds,
3338
+ drawOptions,
3339
+ readLeases,
3340
+ volumeTimingCapture,
3341
+ publication,
3342
+ );
3356
3343
  timingHost.observationFrameId = undefined;
3357
3344
  timingHost.observationCaptureDomains = undefined;
3358
3345
  timingHost.gpuPassTimingFrameIdentity = undefined;
@@ -3400,34 +3387,30 @@ async function makeWebGPURenderer(
3400
3387
  );
3401
3388
  const continuation = createContinuationTerminator();
3402
3389
  frameContinuations.add(continuation);
3403
- const guardedCompletion = completion.then(
3390
+ const guardedCompletion = guardFrameCompletion(
3391
+ completion,
3392
+ () => continuation.guard('queue-completion'),
3404
3393
  () =>
3405
- continuation.guard('queue-completion')
3406
- ? ok(undefined)
3407
- : err(
3408
- new RendererOperationError('device-operation-failed', {
3409
- operation: 'complete-frame',
3410
- frameId: receiptFrameId,
3411
- deviceGeneration: receiptGeneration,
3412
- cause: structuredRendererCause(
3413
- {
3414
- code: 'stale-generation',
3415
- expected: 'frame completion belongs to its device generation',
3416
- hint: 'discard the stale receipt',
3417
- },
3418
- 'complete-frame',
3419
- ),
3420
- }),
3421
- ),
3394
+ new RendererOperationError('device-operation-failed', {
3395
+ operation: 'complete-frame',
3396
+ frameId: receiptFrameId,
3397
+ deviceGeneration: receiptGeneration,
3398
+ cause: structuredRendererCause(
3399
+ {
3400
+ code: 'stale-generation',
3401
+ expected: 'frame completion belongs to its device generation',
3402
+ hint: 'discard the stale receipt',
3403
+ },
3404
+ 'complete-frame',
3405
+ ),
3406
+ }),
3422
3407
  (cause: unknown) =>
3423
- err(
3424
- new RendererOperationError('device-operation-failed', {
3425
- operation: 'complete-frame',
3426
- frameId: receiptFrameId,
3427
- deviceGeneration: receiptGeneration,
3428
- cause: structuredRendererCause(cause, 'complete-frame'),
3429
- }),
3430
- ),
3408
+ new RendererOperationError('device-operation-failed', {
3409
+ operation: 'complete-frame',
3410
+ frameId: receiptFrameId,
3411
+ deviceGeneration: receiptGeneration,
3412
+ cause: structuredRendererCause(cause, 'complete-frame'),
3413
+ }),
3431
3414
  );
3432
3415
  const terminated = continuation.promise().then((reason) =>
3433
3416
  err(
@@ -3455,12 +3438,17 @@ async function makeWebGPURenderer(
3455
3438
  });
3456
3439
  const captures = observationCaptureOwner.consume(receiptFrameId);
3457
3440
  pendingObservationDomains = undefined;
3458
- const receiptGraphGeneration = timingHost.observationGraphGeneration ?? 0;
3441
+ const receiptGraphGeneration =
3442
+ timingHost.observationGraphGeneration ?? renderSystem.perFrameGraphInfo?.generation ?? 0;
3459
3443
  const receipt = Object.freeze({
3460
3444
  frameId: receiptFrameId,
3461
3445
  deviceGeneration: receiptGeneration,
3446
+ presentation: renderSystem.presentation,
3462
3447
  backendId: internals.device.caps.backendKind,
3463
3448
  graphGeneration: receiptGraphGeneration,
3449
+ ...(renderSystem.lastSuccessfulBarrelDistortion === undefined
3450
+ ? {}
3451
+ : { barrelDistortion: renderSystem.lastSuccessfulBarrelDistortion }),
3464
3452
  completed,
3465
3453
  });
3466
3454
  renderTargetHost.onFrameSubmitted(completed);
@@ -3550,6 +3538,10 @@ async function makeWebGPURenderer(
3550
3538
  });
3551
3539
  internals.errorRegistry.fire(e);
3552
3540
  return err(e);
3541
+ } finally {
3542
+ // Native video pixels have been consumed by synchronous queue copy calls.
3543
+ // Release them on every success/failure path, including direct publication users.
3544
+ publicationReceiver?.releaseVideoFrames();
3553
3545
  }
3554
3546
  },
3555
3547
  async observe(
@@ -3792,6 +3784,7 @@ async function makeWebGPURenderer(
3792
3784
  disposed = true;
3793
3785
  for (const world of attachedWorlds) dynamicGeometryHost.invalidateDynamicGeometryWorld(world);
3794
3786
  dynamicGeometry.dispose();
3787
+ publicationReceiver?.dispose();
3795
3788
  for (const continuation of frameContinuations) {
3796
3789
  continuation.terminate({ code: 'disposed' });
3797
3790
  }
@@ -3802,11 +3795,6 @@ async function makeWebGPURenderer(
3802
3795
  }
3803
3796
  for (const world of attachedWorlds) {
3804
3797
  try {
3805
- const derivedSystemName = derivedSystemNames.get(world);
3806
- if (derivedSystemName !== undefined) {
3807
- world.removeSystem(Update, derivedSystemName);
3808
- derivedSystemNames.delete(world);
3809
- }
3810
3798
  transformReleases.get(world)?.();
3811
3799
  transformReleases.delete(world);
3812
3800
  } catch (cause) {
@@ -4055,6 +4043,8 @@ async function makeWebGPURenderer(
4055
4043
  setCandidateEmptyPostProcessBgl(layout) {
4056
4044
  candidateEmptyPostProcessBgl = layout;
4057
4045
  },
4046
+ getShaderModuleAdapter,
4047
+ getImmediateShaderModuleAdapter,
4058
4048
  getShader,
4059
4049
  assets,
4060
4050
  adaptMipmapShaderModuleFactory,