@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
@@ -30,6 +30,7 @@ import type { ManifestEntry } from '@forgeax/engine-types';
30
30
  import { handleSlot } from '@forgeax/engine-types';
31
31
  import { prewarmDepthOfField } from '../features/depth-of-field/depth-of-field-assembly';
32
32
  import { prewarmAtmosphereShaders } from './atmosphere-shader-prewarm';
33
+ import { selectCloudShadowCompatibleEntry } from './cloud-shadow-entry';
33
34
  import { prewarmSsrShaders } from './ssr-shader-prewarm';
34
35
 
35
36
  export type { MaterialShaderManifestEntry } from '@forgeax/engine-shader';
@@ -85,11 +86,10 @@ import { deriveExtendedLightingCapability } from '../prepare/extended-lighting/r
85
86
  import type { BloomPersistentBundle } from '../record/render-context';
86
87
  import { SHADOW_CASTER_BUFFER_SIZE } from '../record/shadow-pass';
87
88
  import { POINTS_LINES_VIEW_BUFFER_SIZE } from '../record/view-ubo';
88
- import {
89
- type AtmosphereShaderSources,
90
- type SsrShaderSources,
91
- STANDARD_OUTPUT_TRANSFORM_FEATURE_ID,
92
- type VolumetricFogShaderSources,
89
+ import type {
90
+ AtmosphereShaderSources,
91
+ SsrShaderSources,
92
+ VolumetricFogShaderSources,
93
93
  } from '../render-contract';
94
94
  import {
95
95
  MATERIAL_PER_ENTITY_STRIDE,
@@ -129,6 +129,7 @@ import {
129
129
  VIEW_UBO_BYTES,
130
130
  } from './webgpu-ready-contract';
131
131
  import { prewarmMipmapPipeline } from './webgpu-ready-mipmap';
132
+ import { createReadyPerPassResources } from './webgpu-ready-per-pass';
132
133
 
133
134
  /**
134
135
  * Build the `Renderer.initialization` Promise (D-S3 three-step strict-serial chain).
@@ -235,8 +236,7 @@ export async function buildReadyWebGPU(
235
236
  ): Promise<PipelineState> {
236
237
  const extendedLightingShaderAvailable = deriveExtendedLightingCapability(rhiDevice).admitted;
237
238
  // Shader and layout construction consume the same storage capability.
238
- const capValue = (rhiDevice.limits as Readonly<Record<string, number>>)
239
- .maxStorageBuffersPerShaderStage;
239
+ const capValue = rhiDevice.limits.maxStorageBuffersPerShaderStage;
240
240
  const webgl2Downlevel = rhiDevice.caps.backendKind === 'wgpu-webgl2';
241
241
  let storageBufferCapable = !webgl2Downlevel && rhiDevice.caps.storageBuffer;
242
242
  if (typeof capValue === 'number') {
@@ -590,11 +590,25 @@ export async function buildReadyWebGPU(
590
590
  return wgsl !== undefined ? { ...entry, wgsl } : entry;
591
591
  };
592
592
  pbrEntry = patchRuntimeVariant(pbrEntry, 'forgeax::default-standard-pbr');
593
+ const pbrMaterialEntry = Array.from(registry.materialShaderManifestEntries()).find(
594
+ (entry) => entry.identifier === 'forgeax::default-standard-pbr',
595
+ );
596
+ pbrEntry = selectCloudShadowCompatibleEntry(pbrEntry, pbrMaterialEntry, projectorAvailable);
593
597
  if (pbrSkinEntry !== undefined) {
594
598
  pbrSkinEntry = patchRuntimeVariant(
595
599
  patchRuntimeVariant(pbrSkinEntry, SKIN_MATERIAL_SHADER_ID),
596
600
  'forgeax::default-standard-pbr-skin',
597
601
  );
602
+ const pbrSkinMaterialEntry = Array.from(registry.materialShaderManifestEntries()).find(
603
+ (entry) =>
604
+ entry.identifier === SKIN_MATERIAL_SHADER_ID ||
605
+ entry.identifier === 'forgeax::default-standard-pbr-skin',
606
+ );
607
+ pbrSkinEntry = selectCloudShadowCompatibleEntry(
608
+ pbrSkinEntry,
609
+ pbrSkinMaterialEntry,
610
+ projectorAvailable,
611
+ );
598
612
  }
599
613
  unlitEntry = patchRuntimeVariant(unlitEntry, 'forgeax::default-unlit');
600
614
  if (shadowCasterEntry !== undefined) {
@@ -693,7 +707,7 @@ export async function buildReadyWebGPU(
693
707
  seedShaderModule,
694
708
  });
695
709
  for (const postProcess of requiredFullscreenPostProcesses) {
696
- const label = postProcessShaderModuleLabel(postProcess.identity, postProcess.source);
710
+ const label = postProcessShaderModuleLabel(postProcess.source);
697
711
  const shaderResult = await runShimStep(
698
712
  () =>
699
713
  asyncCreateShaderModule
@@ -1111,7 +1125,7 @@ export async function buildReadyWebGPU(
1111
1125
  // frames (e.g. the hello-tonemap dawn smoke) would stall on a black frame
1112
1126
  // forever. Mirror the shadow_caster prewarm: await-compile the tonemap module
1113
1127
  // here and `seedShaderModule` it under the exact label
1114
- // `buildPostProcessPipeline` requests (`post-process-${id}-module`), so the
1128
+ // `buildPostProcessPipeline` requests (keyed by shader source), so the
1115
1129
  // first `getPostProcessPipeline(STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, …)` hits the module cache
1116
1130
  // synchronously and builds the pipeline on frame 1.
1117
1131
  const tonemapPrewarm = await runShimStep(
@@ -1119,27 +1133,18 @@ export async function buildReadyWebGPU(
1119
1133
  asyncCreateShaderModule
1120
1134
  ? asyncCreateShaderModule(rhiDevice, {
1121
1135
  code: tonemapEntry.wgsl,
1122
- label: postProcessShaderModuleLabel(
1123
- STANDARD_OUTPUT_TRANSFORM_FEATURE_ID,
1124
- tonemapEntry.wgsl,
1125
- ),
1136
+ label: postProcessShaderModuleLabel(tonemapEntry.wgsl),
1126
1137
  })
1127
1138
  : invokeDeviceCreateShaderModule(rhiDevice, {
1128
1139
  code: tonemapEntry.wgsl,
1129
- label: postProcessShaderModuleLabel(
1130
- STANDARD_OUTPUT_TRANSFORM_FEATURE_ID,
1131
- tonemapEntry.wgsl,
1132
- ),
1140
+ label: postProcessShaderModuleLabel(tonemapEntry.wgsl),
1133
1141
  }),
1134
1142
  'shader-compile-failed',
1135
1143
  'tonemap shader module compiled (unified post-process prewarm)',
1136
1144
  'inspect manifest tonemap entry composed wgsl; check device.features',
1137
1145
  );
1138
1146
  if (!tonemapPrewarm.ok) throw tonemapPrewarm.error;
1139
- seedShaderModule(
1140
- postProcessShaderModuleLabel(STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, tonemapEntry.wgsl),
1141
- tonemapPrewarm.value,
1142
- );
1147
+ seedShaderModule(postProcessShaderModuleLabel(tonemapEntry.wgsl), tonemapPrewarm.value);
1143
1148
  registerBuiltinTonemap(tonemapEntry.wgsl);
1144
1149
 
1145
1150
  // Prewarm temporal fullscreen modules before readiness so first-frame
@@ -1309,6 +1314,12 @@ export async function buildReadyWebGPU(
1309
1314
  if (!fxaaShaderResult.ok) throw fxaaShaderResult.error;
1310
1315
  fxaaModule = fxaaShaderResult.value;
1311
1316
  registerBuiltinFxaa(fxaaEntry.wgsl);
1317
+ // The typed graph may need a second FXAA pipeline for a graph-owned
1318
+ // linear-LDR target (for example BarrelDistortion + FXAA). Seed the
1319
+ // shared post-process adapter with the already compiled module so that
1320
+ // this alternate color format is available on the first submitted
1321
+ // frame instead of waiting for an async recompile.
1322
+ seedShaderModule(postProcessShaderModuleLabel(fxaaEntry.wgsl), fxaaModule);
1312
1323
  }
1313
1324
 
1314
1325
  // feat-20260531-skybox-env-background M3 / w15: skybox shader module.
@@ -1428,7 +1439,7 @@ export async function buildReadyWebGPU(
1428
1439
  // instances) and the 4-slot pipeline layout in one call, throwing on each
1429
1440
  // device.createBindGroupLayout / device.createPipelineLayout failure.
1430
1441
  // material BGL now carries 24 entries (canonical material 0..14 + Skylight
1431
- // 15..21 + transmission 22..23); authored physical maps append after the
1442
+ // 15..20 + transmission 21..22); authored physical maps append after the
1432
1443
  // engine-owned injections. The pipeline layout itself stays at 4 slots, no
1433
1444
  // @group(4) allocated (D-5 round-4 fix for the round-2 maxBindGroups=4
1434
1445
  // BLOCKER). The standalone unlit BGL is the 15-entry user region exposed by
@@ -1479,6 +1490,7 @@ export async function buildReadyWebGPU(
1479
1490
  let hdrpPbrPipelineLayoutHandle: PipelineLayout | null = null;
1480
1491
  let hdrpMeshBindGroupLayoutHandle: BindGroupLayout | null = null;
1481
1492
  let hdrpProbePbrPipelineLayoutHandle: PipelineLayout | null = null;
1493
+ let hdrpUnifiedBglHandle: BindGroupLayout | null = null;
1482
1494
  // The cluster layout is storage-buffer backed. On the WebGL2/fallback
1483
1495
  // capability tier its uniform-buffer projection exceeds the backend's
1484
1496
  // fragment-stage limit, and HDRP is not a valid route there anyway.
@@ -1486,6 +1498,7 @@ export async function buildReadyWebGPU(
1486
1498
  const hdrpUnifiedBglDesc = createHdrpBindGroupLayoutDescriptor();
1487
1499
  const hdrpUnifiedBglRes = rhiDevice.createBindGroupLayout(hdrpUnifiedBglDesc);
1488
1500
  if (hdrpUnifiedBglRes.ok) {
1501
+ hdrpUnifiedBglHandle = hdrpUnifiedBglRes.value;
1489
1502
  hdrpMeshBindGroupLayoutHandle = hdrpUnifiedBglRes.value;
1490
1503
  const hdrpPlRes = rhiDevice.createPipelineLayout({
1491
1504
  label: 'hdrp-pbr-pl',
@@ -1571,6 +1584,7 @@ export async function buildReadyWebGPU(
1571
1584
  gpuDrivenInstancesBindGroupLayout: gpuDrivenInstancesBindGroupLayoutHandle,
1572
1585
  gpuDrivenPbrPipelineLayout: gpuDrivenPbrPipelineLayoutHandle,
1573
1586
  gpuDrivenPbrSkinPipelineLayout: gpuDrivenPbrSkinPipelineLayoutHandle,
1587
+ surfaceDirectInstancesBindGroupLayout: surfaceDirectInstancesBindGroupLayoutHandle,
1574
1588
  } = buildGpuDrivenPbrReadyLayouts(rhiDevice, storageBufferCapable, pbrLayouts.value);
1575
1589
  let hdrpSkinPipelineLayoutHandle: PipelineLayout | null = null;
1576
1590
  let hdrpSkinMeshBindGroupLayoutHandle: BindGroupLayout | null = null;
@@ -1595,6 +1609,46 @@ export async function buildReadyWebGPU(
1595
1609
  }
1596
1610
  }
1597
1611
 
1612
+ // GPU-driven Standard batches use the compact scene-index slot(3) while
1613
+ // retaining the same clustered group(2) bind group that the ordinary main
1614
+ // pass publishes. Build a matching pipeline layout from those exact
1615
+ // producer-owned layouts; a separate URP mesh-array layout would validate
1616
+ // the indirect draw but reject its clustered bind group at encode time.
1617
+ let gpuDrivenClusterPbrPipelineLayoutHandle: PipelineLayout | null = null;
1618
+ let gpuDrivenClusterPbrSkinPipelineLayoutHandle: PipelineLayout | null = null;
1619
+ if (
1620
+ storageBufferCapable &&
1621
+ hdrpUnifiedBglHandle !== null &&
1622
+ gpuDrivenInstancesBindGroupLayoutHandle !== null
1623
+ ) {
1624
+ const rigidResult = rhiDevice.createPipelineLayout({
1625
+ label: 'pbr-gpu-driven-cluster-pl',
1626
+ bindGroupLayouts: [
1627
+ viewBglResult.value,
1628
+ materialBglResult.value,
1629
+ hdrpUnifiedBglHandle,
1630
+ gpuDrivenInstancesBindGroupLayoutHandle,
1631
+ ],
1632
+ });
1633
+ if (rigidResult.ok) gpuDrivenClusterPbrPipelineLayoutHandle = rigidResult.value;
1634
+ }
1635
+ if (
1636
+ storageBufferCapable &&
1637
+ hdrpSkinMeshBindGroupLayoutHandle !== null &&
1638
+ gpuDrivenInstancesBindGroupLayoutHandle !== null
1639
+ ) {
1640
+ const skinResult = rhiDevice.createPipelineLayout({
1641
+ label: 'pbr-skin-gpu-driven-cluster-pl',
1642
+ bindGroupLayouts: [
1643
+ viewBglResult.value,
1644
+ materialBglResult.value,
1645
+ hdrpSkinMeshBindGroupLayoutHandle,
1646
+ gpuDrivenInstancesBindGroupLayoutHandle,
1647
+ ],
1648
+ });
1649
+ if (skinResult.ok) gpuDrivenClusterPbrSkinPipelineLayoutHandle = skinResult.value;
1650
+ }
1651
+
1598
1652
  // feat-20260612-skin-palette-per-frame-upload M1 / m1-2: skin palette
1599
1653
  // allocator. Replaces the prior 16320 B identity-seeded UBO stub (PR #353,
1600
1654
  // feat-20260611 R2 / M8 / w28 IS-14, retired identity-buffer field) with
@@ -1622,9 +1676,7 @@ export async function buildReadyWebGPU(
1622
1676
  const skinPaletteLimitKey = storageBufferCapable
1623
1677
  ? 'maxStorageBufferBindingSize'
1624
1678
  : 'maxUniformBufferBindingSize';
1625
- const skinPaletteDeviceLimit = (rhiDevice.limits as Readonly<Record<string, number>>)[
1626
- skinPaletteLimitKey
1627
- ];
1679
+ const skinPaletteDeviceLimit = rhiDevice.limits[skinPaletteLimitKey];
1628
1680
  const SKIN_PALETTE_MAX_BINDING_BYTES =
1629
1681
  typeof skinPaletteDeviceLimit === 'number' && skinPaletteDeviceLimit > 0
1630
1682
  ? skinPaletteDeviceLimit
@@ -2016,6 +2068,24 @@ export async function buildReadyWebGPU(
2016
2068
  );
2017
2069
  if (!defaultSamplerResult.ok) throw defaultSamplerResult.error;
2018
2070
 
2071
+ // r32float Surface raw-depth views are unfilterable. Keep their sampler
2072
+ // distinct from the filtering material sampler so WebGPU's sample-type
2073
+ // validation remains explicit at the material BGL boundary.
2074
+ const surfaceMediumDepthSamplerResult = runShimSyncStep(
2075
+ () =>
2076
+ rhiDevice.createSampler({
2077
+ label: 'surface-medium-depth-sampler',
2078
+ magFilter: 'nearest',
2079
+ minFilter: 'nearest',
2080
+ addressModeU: 'clamp-to-edge',
2081
+ addressModeV: 'clamp-to-edge',
2082
+ }),
2083
+ 'webgpu-runtime-error',
2084
+ 'createSampler (single-layer medium raw depth) succeeded',
2085
+ 'check device.limits.maxSamplersPerShaderStage',
2086
+ );
2087
+ if (!surfaceMediumDepthSamplerResult.ok) throw surfaceMediumDepthSamplerResult.error;
2088
+
2019
2089
  // feat-20260520-directional-light-shadow-mapping M1c / w8 + M2 / w14:
2020
2090
  // shadow comparison sampler — clamp-to-edge, linear filter, compare:'less'.
2021
2091
  // Used for shadow map sampling in M2/M3 and shadow depth pass. comparison
@@ -3879,6 +3949,18 @@ export async function buildReadyWebGPU(
3879
3949
  gpuDrivenPbrPrograms,
3880
3950
  gpuDrivenPbrSkinPipelineLayout:
3881
3951
  unlitModule !== null && pbrModule !== null ? gpuDrivenPbrSkinPipelineLayoutHandle : null,
3952
+ surfaceDirectInstancesBindGroupLayout:
3953
+ unlitModule !== null && pbrModule !== null
3954
+ ? surfaceDirectInstancesBindGroupLayoutHandle
3955
+ : null,
3956
+ gpuDrivenClusterPbrPipelineLayout:
3957
+ unlitModule !== null && pbrModule !== null ? gpuDrivenClusterPbrPipelineLayoutHandle : null,
3958
+ gpuDrivenClusterPbrSkinPipelineLayout:
3959
+ unlitModule !== null && pbrModule !== null
3960
+ ? gpuDrivenClusterPbrSkinPipelineLayoutHandle
3961
+ : null,
3962
+ gpuDrivenClusterMeshBindGroupLayout:
3963
+ unlitModule !== null && pbrModule !== null ? hdrpUnifiedBglHandle : null,
3882
3964
  // HDRP variant uses the unified group(2) layout built above.
3883
3965
  hdrpPbrPipelineLayout:
3884
3966
  unlitModule !== null && pbrModule !== null ? hdrpPbrPipelineLayoutHandle : null,
@@ -3924,6 +4006,7 @@ export async function buildReadyWebGPU(
3924
4006
  probeInstancesBindGroupLayout: probeInstancesBglResult.value,
3925
4007
  identityInstanceBuffer: identityInstanceResult.value,
3926
4008
  defaultSampler: defaultSamplerResult.value,
4009
+ surfaceMediumDepthSampler: surfaceMediumDepthSamplerResult.value,
3927
4010
  fallbackTextureView: fallbackTextureViewResult.value,
3928
4011
  defaultWhiteTextureView: fallbackTextureViewResult.value,
3929
4012
  // Exactly neutral half-float RG=(0.5,0.5) decodes to tangent (0,0,1).
@@ -3952,44 +4035,15 @@ export async function buildReadyWebGPU(
3952
4035
  // matrices fold into the View UBO tail (`view.spotLightViewProj`); no
3953
4036
  // dedicated buffer / view-BG binding 9 (WebGL2 uniform-buffer budget).
3954
4037
  skylightFallback,
3955
- // feat-20260529-rendergraph-pass-abstraction M3 / w11 (D-2 + Finding 3):
3956
- // per-pass mutable resource slots moved to PerPassResources.
3957
- perPassResources: {
3958
- depthTexture: null,
3959
- depthTextureView: null,
3960
- depthTextureWidth: 0,
3961
- depthTextureHeight: 0,
3962
- configured: false,
3963
- hdrColorTexture: null,
3964
- hdrColorView: null,
3965
- hdrDepthTexture: null,
3966
- hdrDepthView: null,
3967
- hdrTextureWidth: 0,
3968
- hdrTextureHeight: 0,
3969
- hdrDepthSampleCount: 1,
4038
+ perPassResources: createReadyPerPassResources({
3970
4039
  fxaaPipeline: fxaaPipelineHandle,
3971
4040
  fxaaBindGroupLayout: fxaaBglHandle,
3972
4041
  fxaaSampler: fxaaSamplerHandle,
3973
- // feat-20260604-learn-render-4.10-anti-aliasing-msaa M2 / w7: MSAA
3974
- // attachment slots. All null/0 until the first antialias='msaa' frame.
3975
- msaaColorTexture: null,
3976
- msaaColorView: null,
3977
- msaaSpriteColorTexture: null,
3978
- msaaSpriteColorView: null,
3979
- msaaDepthTexture: null,
3980
- msaaDepthView: null,
3981
- msaaTextureWidth: 0,
3982
- msaaTextureHeight: 0,
3983
- hdrColorMsaaTexture: null,
3984
- hdrColorMsaaView: null,
3985
4042
  skyboxPipeline: skyboxPipelineHandle,
3986
4043
  skyboxPipelineMsaa: skyboxPipelineMsaaHandle,
3987
4044
  skyboxBindGroupLayout: skyboxBglHandle,
3988
4045
  skyboxSampler: skyboxSamplerHandle,
3989
4046
  skyboxRotationBuffer: skyboxRotationBufferHandle,
3990
- shadowTexture: null,
3991
- shadowMapSize: 0,
3992
- shadowCascadeCount: 0,
3993
4047
  shadowSampler: shadowSamplerResult.value,
3994
4048
  shadowLightSpaceMatrix: null,
3995
4049
  shadowCsmLightViewProj: null,
@@ -4020,13 +4074,13 @@ export async function buildReadyWebGPU(
4020
4074
  ssaoCalcPipeline: ssaoCalcPipelineHandle,
4021
4075
  ssaoBlurPipeline: ssaoBlurPipelineHandle,
4022
4076
  ssaoBgl: ssaoBglHandle,
4023
- // M8 / w38: lazy-allocated on first SSAO record frame. Sampler kinds
4024
- // and the 1x1 ssaoRaw fallback view are constant across frames and
4025
- // cached after first construction.
4026
- ssaoFilteringSampler: null,
4027
- ssaoDepthSampler: null,
4028
- ssaoFallbackRawView: null,
4029
- },
4077
+ }),
4030
4078
  };
4079
+ // Boot-time fallback resources submit real GPU work before the renderer is
4080
+ // published. Keep initialization as the readiness barrier for the first
4081
+ // frame: a Worker can otherwise receive `ready`, start its frame deadline,
4082
+ // and report `frame-submitted` while that earlier queue work still holds the
4083
+ // receipt's completion fence.
4084
+ await queue.onSubmittedWorkDone();
4031
4085
  return pipelineState;
4032
4086
  }
@@ -53,18 +53,6 @@ export async function tryCreateWebGPURenderer(
53
53
  onDeviceLost: (detail) => lossObserver.current?.(detail),
54
54
  });
55
55
 
56
- if (pack._internal_getRawDevice && pack.translateErrorEventToRhiError) {
57
- const backendDevice = pack._internal_getRawDevice(device);
58
- if (backendDevice && typeof backendDevice === 'object') {
59
- const target = backendDevice as {
60
- onuncapturederror?: ((event: unknown) => void) | null;
61
- };
62
- target.onuncapturederror = (event: unknown): void => {
63
- const translated = pack.translateErrorEventToRhiError?.(event);
64
- if (translated && !translated.ok) errorRegistry.fire(translated.error);
65
- };
66
- }
67
- }
68
56
  return {
69
57
  kind: 'ok',
70
58
  renderer: await createRenderer({
@@ -0,0 +1,222 @@
1
+ import type { Buffer } from '@forgeax/engine-rhi';
2
+ import { err, ok } from '@forgeax/engine-rhi';
3
+ import { type RenderError, RendererContractFailureError } from '../errors/render';
4
+ import type { FrameReceipt, RenderResult } from '../render-contract';
5
+ import type { TypedFrameObservationCapture } from '../typed-render-graph-primitives';
6
+ import { disposeObservationCaptureSet } from './webgpu-renderer-observation';
7
+
8
+ export type ObservationCaptureRead = () => Promise<
9
+ RenderResult<
10
+ readonly {
11
+ readonly capture: TypedFrameObservationCapture;
12
+ readonly bytes: Uint8Array;
13
+ }[],
14
+ RenderError
15
+ >
16
+ >;
17
+
18
+ export interface RendererObservationCaptureOwner {
19
+ readonly observationCaptureOwner: {
20
+ register(capture: TypedFrameObservationCapture): void;
21
+ consume(frameNumber: number): readonly TypedFrameObservationCapture[];
22
+ drain(): readonly TypedFrameObservationCapture[];
23
+ };
24
+ readonly stats: {
25
+ allocationCount: number;
26
+ liveCount: number;
27
+ peakLiveCount: number;
28
+ mapCount: number;
29
+ readbackCount: number;
30
+ liveByteLength: number;
31
+ };
32
+ expectedGraphGeneration: number | undefined;
33
+ readonly receiptObservationCaptures: Map<FrameReceipt, ObservationCaptureRead>;
34
+ readonly receiptObservationBuffers: Map<FrameReceipt, readonly TypedFrameObservationCapture[]>;
35
+ readonly destroyedObservationBuffers: WeakSet<Buffer>;
36
+ readonly observationBufferCleanupFailures: WeakMap<Buffer, RendererContractFailureError>;
37
+ readonly failedObservationCaptures: Map<Buffer, TypedFrameObservationCapture>;
38
+ readonly disposeObservationCaptures: (
39
+ captures: readonly TypedFrameObservationCapture[],
40
+ ) => RendererContractFailureError | undefined;
41
+ readonly disposeOwnedObservationCaptures: (
42
+ captures: readonly TypedFrameObservationCapture[],
43
+ ) => RendererContractFailureError | undefined;
44
+ readonly readObservationCapture: (
45
+ capture: TypedFrameObservationCapture,
46
+ ) => Promise<RenderResult<Uint8Array, RenderError>>;
47
+ readonly disposeReceiptObservationCaptures: () => RendererContractFailureError | undefined;
48
+ }
49
+
50
+ export function createRendererObservationCaptureOwner(
51
+ fireError: (error: RendererContractFailureError) => void,
52
+ ): RendererObservationCaptureOwner {
53
+ const stats = {
54
+ allocationCount: 0,
55
+ liveCount: 0,
56
+ peakLiveCount: 0,
57
+ mapCount: 0,
58
+ readbackCount: 0,
59
+ liveByteLength: 0,
60
+ };
61
+ const capturesByFrame = new Map<number, TypedFrameObservationCapture[]>();
62
+ const observationCaptureOwner = {
63
+ register(capture: TypedFrameObservationCapture): void {
64
+ const captures = capturesByFrame.get(capture.frameNumber) ?? [];
65
+ captures.push(capture);
66
+ capturesByFrame.set(capture.frameNumber, captures);
67
+ stats.allocationCount += 1;
68
+ stats.liveCount += 1;
69
+ stats.peakLiveCount = Math.max(stats.peakLiveCount, stats.liveCount);
70
+ stats.liveByteLength += capture.bytesPerRow * capture.height;
71
+ },
72
+ consume(frameNumber: number): readonly TypedFrameObservationCapture[] {
73
+ const captures = capturesByFrame.get(frameNumber) ?? [];
74
+ capturesByFrame.delete(frameNumber);
75
+ return Object.freeze(captures);
76
+ },
77
+ drain(): readonly TypedFrameObservationCapture[] {
78
+ const captures = [...capturesByFrame.values()].flat();
79
+ capturesByFrame.clear();
80
+ return Object.freeze(captures);
81
+ },
82
+ };
83
+ const destroyedObservationBuffers = new WeakSet<Buffer>();
84
+ const observationBufferCleanupFailures = new WeakMap<Buffer, RendererContractFailureError>();
85
+ const failedObservationCaptures = new Map<Buffer, TypedFrameObservationCapture>();
86
+ const disposeObservationCaptures = (
87
+ captures: readonly TypedFrameObservationCapture[],
88
+ ): RendererContractFailureError | undefined => {
89
+ const wasDestroyed = new Set(
90
+ captures
91
+ .filter((capture) => destroyedObservationBuffers.has(capture.buffer))
92
+ .map((capture) => capture.buffer),
93
+ );
94
+ const result = disposeObservationCaptureSet(
95
+ captures,
96
+ destroyedObservationBuffers,
97
+ observationBufferCleanupFailures,
98
+ fireError,
99
+ );
100
+ for (const capture of captures) {
101
+ if (!wasDestroyed.has(capture.buffer) && destroyedObservationBuffers.has(capture.buffer)) {
102
+ stats.liveCount = Math.max(0, stats.liveCount - 1);
103
+ stats.liveByteLength = Math.max(
104
+ 0,
105
+ stats.liveByteLength - capture.bytesPerRow * capture.height,
106
+ );
107
+ }
108
+ }
109
+ return result;
110
+ };
111
+ const disposeOwnedObservationCaptures = (
112
+ captures: readonly TypedFrameObservationCapture[],
113
+ ): RendererContractFailureError | undefined => {
114
+ const failure = disposeObservationCaptures(captures);
115
+ if (failure !== undefined) {
116
+ for (const capture of captures) {
117
+ if (!destroyedObservationBuffers.has(capture.buffer)) {
118
+ failedObservationCaptures.set(capture.buffer, capture);
119
+ }
120
+ }
121
+ }
122
+ return failure;
123
+ };
124
+ const readObservationCapture = async (
125
+ capture: TypedFrameObservationCapture,
126
+ ): Promise<RenderResult<Uint8Array, RenderError>> => {
127
+ try {
128
+ if (typeof capture.buffer.mapAsync !== 'function') {
129
+ const cleanupFailure = disposeObservationCaptures([capture]);
130
+ return err(
131
+ cleanupFailure ??
132
+ new RendererContractFailureError(
133
+ 'observe',
134
+ `the ${capture.domain} receipt-bound readback backend has no mapAsync capability`,
135
+ ),
136
+ );
137
+ }
138
+ stats.mapCount += 1;
139
+ const mapped = await capture.buffer.mapAsync(1);
140
+ if (!mapped.ok) {
141
+ const cleanupFailure = disposeObservationCaptures([capture]);
142
+ return err(
143
+ cleanupFailure ??
144
+ new RendererContractFailureError(
145
+ 'observe',
146
+ `mapping ${capture.domain} receipt-bound readback failed: ${mapped.error.code}`,
147
+ ),
148
+ );
149
+ }
150
+ const range = mapped.value.getMappedRange();
151
+ if (!range.ok) {
152
+ mapped.value.unmap();
153
+ const cleanupFailure = disposeObservationCaptures([capture]);
154
+ return err(
155
+ cleanupFailure ??
156
+ new RendererContractFailureError(
157
+ 'observe',
158
+ `reading ${capture.domain} receipt-bound readback failed: ${range.error.code}`,
159
+ ),
160
+ );
161
+ }
162
+ const bytes = new Uint8Array(range.value.slice(0));
163
+ mapped.value.unmap();
164
+ stats.readbackCount += 1;
165
+ const cleanupFailure = disposeObservationCaptures([capture]);
166
+ if (cleanupFailure !== undefined) return err(cleanupFailure);
167
+ return ok(bytes);
168
+ } catch (cause) {
169
+ const cleanupFailure = disposeObservationCaptures([capture]);
170
+ return err(
171
+ cleanupFailure ??
172
+ new RendererContractFailureError(
173
+ 'observe',
174
+ `reading ${capture.domain} receipt-bound readback threw: ${
175
+ cause instanceof Error ? cause.message : String(cause)
176
+ }`,
177
+ ),
178
+ );
179
+ }
180
+ };
181
+ const receiptObservationCaptures = new Map<FrameReceipt, ObservationCaptureRead>();
182
+ const receiptObservationBuffers = new Map<
183
+ FrameReceipt,
184
+ readonly TypedFrameObservationCapture[]
185
+ >();
186
+ const owner: RendererObservationCaptureOwner = {
187
+ observationCaptureOwner,
188
+ stats,
189
+ expectedGraphGeneration: undefined,
190
+ receiptObservationCaptures,
191
+ receiptObservationBuffers,
192
+ destroyedObservationBuffers,
193
+ observationBufferCleanupFailures,
194
+ failedObservationCaptures,
195
+ disposeObservationCaptures,
196
+ disposeOwnedObservationCaptures,
197
+ readObservationCapture,
198
+ disposeReceiptObservationCaptures: () => {
199
+ let firstFailure: RendererContractFailureError | undefined;
200
+ for (const [receipt, captures] of receiptObservationBuffers) {
201
+ const failure = disposeObservationCaptures(captures);
202
+ firstFailure ??= failure;
203
+ if (captures.every((capture) => destroyedObservationBuffers.has(capture.buffer))) {
204
+ receiptObservationBuffers.delete(receipt);
205
+ }
206
+ }
207
+ receiptObservationCaptures.clear();
208
+ const retryCaptures = [...failedObservationCaptures.values()];
209
+ const retryFailure = disposeObservationCaptures(retryCaptures);
210
+ firstFailure ??= retryFailure;
211
+ for (const capture of retryCaptures) {
212
+ if (destroyedObservationBuffers.has(capture.buffer)) {
213
+ failedObservationCaptures.delete(capture.buffer);
214
+ }
215
+ }
216
+ const ownedFailure = disposeOwnedObservationCaptures(observationCaptureOwner.drain());
217
+ firstFailure ??= ownedFailure;
218
+ return firstFailure;
219
+ },
220
+ };
221
+ return owner;
222
+ }