@forgeax/engine-render 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/README.md +1374 -142
  2. package/dist/assembly/analytic-fog-registration.d.ts +3 -0
  3. package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
  4. package/dist/assembly/backend-contract.d.ts +2 -0
  5. package/dist/assembly/backend-contract.d.ts.map +1 -1
  6. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  7. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  8. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  9. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  10. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  11. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  12. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  13. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  15. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  16. package/dist/assembly/factory.d.ts +1 -1
  17. package/dist/assembly/factory.d.ts.map +1 -1
  18. package/dist/assembly/fxaa-registration.d.ts +4 -0
  19. package/dist/assembly/fxaa-registration.d.ts.map +1 -0
  20. package/dist/assembly/host-contract.d.ts +3 -3
  21. package/dist/assembly/host-contract.d.ts.map +1 -1
  22. package/dist/assembly/lod-observation.d.ts +4 -0
  23. package/dist/assembly/lod-observation.d.ts.map +1 -0
  24. package/dist/assembly/material/assembly.d.ts.map +1 -1
  25. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  26. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  27. package/dist/assembly/material-shader-policy.d.ts +16 -2
  28. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  29. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  30. package/dist/assembly/motion-blur-registration.d.ts +3 -0
  31. package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
  32. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  33. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  34. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  35. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  36. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  37. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  38. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  39. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  40. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  41. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  42. package/dist/assembly/renderer-inspection.d.ts +11 -0
  43. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  44. package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
  45. package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  47. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  48. package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
  49. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -1
  50. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  51. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  52. package/dist/assembly/webgpu-ready.d.ts +2 -2
  53. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  54. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  55. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  56. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  57. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  58. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  59. package/dist/authoring.mjs +1 -1
  60. package/dist/barrel-distortion.d.ts +47 -0
  61. package/dist/barrel-distortion.d.ts.map +1 -0
  62. package/dist/bloom-admission.d.ts +13 -0
  63. package/dist/bloom-admission.d.ts.map +1 -0
  64. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  65. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  66. package/dist/{chunk-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
  67. package/dist/chunk-HEB564WF.mjs.map +1 -0
  68. package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
  69. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  70. package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
  71. package/dist/{chunk-S665NJNF.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  72. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  73. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  74. package/dist/{chunk-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
  75. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  76. package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
  77. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  78. package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
  79. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  80. package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
  81. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  82. package/dist/cloud/density.d.ts +55 -0
  83. package/dist/cloud/density.d.ts.map +1 -0
  84. package/dist/cloud/extract.d.ts +25 -0
  85. package/dist/cloud/extract.d.ts.map +1 -0
  86. package/dist/cloud/feature.d.ts +57 -0
  87. package/dist/cloud/feature.d.ts.map +1 -0
  88. package/dist/cloud/frame-context.d.ts +8 -0
  89. package/dist/cloud/frame-context.d.ts.map +1 -0
  90. package/dist/cloud/inspection.d.ts +59 -0
  91. package/dist/cloud/inspection.d.ts.map +1 -0
  92. package/dist/cloud/optics.d.ts +56 -0
  93. package/dist/cloud/optics.d.ts.map +1 -0
  94. package/dist/cloud/parameters.d.ts +73 -0
  95. package/dist/cloud/parameters.d.ts.map +1 -0
  96. package/dist/cloud/resources.d.ts +60 -0
  97. package/dist/cloud/resources.d.ts.map +1 -0
  98. package/dist/cloud/shadow.d.ts +42 -0
  99. package/dist/cloud/shadow.d.ts.map +1 -0
  100. package/dist/cloud/temporal.d.ts +74 -0
  101. package/dist/cloud/temporal.d.ts.map +1 -0
  102. package/dist/components/atmosphere.d.ts +2 -0
  103. package/dist/components/atmosphere.d.ts.map +1 -1
  104. package/dist/components/barrel-distortion.d.ts +13 -0
  105. package/dist/components/barrel-distortion.d.ts.map +1 -0
  106. package/dist/components/camera.d.ts +20 -4
  107. package/dist/components/camera.d.ts.map +1 -1
  108. package/dist/components/cloud-layer.d.ts +29 -0
  109. package/dist/components/cloud-layer.d.ts.map +1 -0
  110. package/dist/components/index.d.ts +2 -0
  111. package/dist/components/index.d.ts.map +1 -1
  112. package/dist/components/instances.d.ts +20 -6
  113. package/dist/components/instances.d.ts.map +1 -1
  114. package/dist/components/mesh-filter.d.ts +6 -5
  115. package/dist/components/mesh-filter.d.ts.map +1 -1
  116. package/dist/components/motion-blur.d.ts +1 -0
  117. package/dist/components/motion-blur.d.ts.map +1 -1
  118. package/dist/construct-renderer.d.ts +1 -1
  119. package/dist/construct-renderer.d.ts.map +1 -1
  120. package/dist/construct-renderer.mjs +9751 -3528
  121. package/dist/construct-renderer.mjs.map +1 -1
  122. package/dist/device/gpu-residency.d.ts +6 -0
  123. package/dist/device/gpu-residency.d.ts.map +1 -1
  124. package/dist/dynamic-geometry.d.ts +5 -1
  125. package/dist/dynamic-geometry.d.ts.map +1 -1
  126. package/dist/environment/analytic-fog.d.ts +6 -0
  127. package/dist/environment/analytic-fog.d.ts.map +1 -0
  128. package/dist/errors/cloud.d.ts +59 -0
  129. package/dist/errors/cloud.d.ts.map +1 -0
  130. package/dist/errors/render.d.ts +23 -5
  131. package/dist/errors/render.d.ts.map +1 -1
  132. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  133. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  134. package/dist/extract/camera.d.ts.map +1 -1
  135. package/dist/extract/contracts.d.ts +12 -1
  136. package/dist/extract/contracts.d.ts.map +1 -1
  137. package/dist/extract/environment.d.ts +2 -0
  138. package/dist/extract/environment.d.ts.map +1 -1
  139. package/dist/features/barrel-distortion.d.ts +29 -0
  140. package/dist/features/barrel-distortion.d.ts.map +1 -0
  141. package/dist/features/error-reporting.d.ts +17 -0
  142. package/dist/features/error-reporting.d.ts.map +1 -0
  143. package/dist/features/host.d.ts +15 -0
  144. package/dist/features/host.d.ts.map +1 -1
  145. package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
  146. package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
  147. package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
  148. package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
  149. package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
  150. package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
  151. package/dist/features/plan.d.ts +15 -4
  152. package/dist/features/plan.d.ts.map +1 -1
  153. package/dist/features/prepared-gpu-work.d.ts +9 -5
  154. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  155. package/dist/features/render-graph-compute.d.ts.map +1 -1
  156. package/dist/features/render-graph-contribution.d.ts +5 -0
  157. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  158. package/dist/features/render-graph-raster.d.ts +1 -0
  159. package/dist/features/render-graph-raster.d.ts.map +1 -1
  160. package/dist/features/targets.d.ts +2 -0
  161. package/dist/features/targets.d.ts.map +1 -1
  162. package/dist/features/types.d.ts +44 -0
  163. package/dist/features/types.d.ts.map +1 -1
  164. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  165. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  166. package/dist/gpu-dirty-ranges.d.ts +11 -0
  167. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  168. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  169. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  170. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  171. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  172. package/dist/gpu-driven/prepared-draw.d.ts +7 -0
  173. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  174. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  175. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  176. package/dist/gpu-driven/production-raster.d.ts +50 -4
  177. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  178. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  179. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  180. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  181. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  182. package/dist/gpu-driven/view-gpu.d.ts +35 -2
  183. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  184. package/dist/gpu-scene.d.ts +11 -1
  185. package/dist/gpu-scene.d.ts.map +1 -1
  186. package/dist/hdrp-buffers.d.ts +2 -2
  187. package/dist/hdrp-buffers.d.ts.map +1 -1
  188. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  189. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  190. package/dist/index.d.ts +31 -8
  191. package/dist/index.d.ts.map +1 -1
  192. package/dist/index.mjs +258 -8
  193. package/dist/index.mjs.map +1 -1
  194. package/dist/inspection-types.d.ts +178 -3
  195. package/dist/inspection-types.d.ts.map +1 -1
  196. package/dist/instance-buffer-cache.d.ts +4 -4
  197. package/dist/instance-buffer-cache.d.ts.map +1 -1
  198. package/dist/instances.d.ts +49 -94
  199. package/dist/instances.d.ts.map +1 -1
  200. package/dist/internal.mjs +7 -7
  201. package/dist/pbr-pipeline.d.ts +19 -1
  202. package/dist/pbr-pipeline.d.ts.map +1 -1
  203. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  204. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  205. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  206. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  207. package/dist/pipeline/standard-output/types.d.ts +4 -2
  208. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  209. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  210. package/dist/pipeline/standard-post.d.ts +28 -19
  211. package/dist/pipeline/standard-post.d.ts.map +1 -1
  212. package/dist/pipeline-builder.d.ts +1 -1
  213. package/dist/pipeline-builder.d.ts.map +1 -1
  214. package/dist/pipeline-spec.d.ts +2 -2
  215. package/dist/plugin.d.ts.map +1 -1
  216. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  217. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  218. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  219. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  220. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  221. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  222. package/dist/record/fold-buckets.d.ts +95 -0
  223. package/dist/record/fold-buckets.d.ts.map +1 -0
  224. package/dist/record/fold-instance-buffer.d.ts +6 -0
  225. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  226. package/dist/record/frame-lighting.d.ts +1 -0
  227. package/dist/record/frame-lighting.d.ts.map +1 -1
  228. package/dist/record/frame-snapshot.d.ts +40 -3
  229. package/dist/record/frame-snapshot.d.ts.map +1 -1
  230. package/dist/record/frame-targets.d.ts.map +1 -1
  231. package/dist/record/frame.d.ts +14 -62
  232. package/dist/record/frame.d.ts.map +1 -1
  233. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  234. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  235. package/dist/record/gpu-timing.d.ts +8 -0
  236. package/dist/record/gpu-timing.d.ts.map +1 -1
  237. package/dist/record/main-pass-geometry.d.ts +21 -5
  238. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  239. package/dist/record/main-pass-material.d.ts +7 -1
  240. package/dist/record/main-pass-material.d.ts.map +1 -1
  241. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  242. package/dist/record/main-pass.d.ts +13 -2
  243. package/dist/record/main-pass.d.ts.map +1 -1
  244. package/dist/record/mesh-ssbo.d.ts +6 -5
  245. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  246. package/dist/record/motion-blur-receipt.d.ts +11 -0
  247. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  248. package/dist/record/probe-blend-buffer.d.ts +16 -0
  249. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  250. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  251. package/dist/record/render-context.d.ts +34 -31
  252. package/dist/record/render-context.d.ts.map +1 -1
  253. package/dist/record/shadow-pass.d.ts +2 -0
  254. package/dist/record/shadow-pass.d.ts.map +1 -1
  255. package/dist/record/skybox-post-pass.d.ts +6 -4
  256. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  257. package/dist/record/typed-frame-graph.d.ts +22 -2
  258. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  259. package/dist/record/view-ubo.d.ts +11 -3
  260. package/dist/record/view-ubo.d.ts.map +1 -1
  261. package/dist/record/volume-params.d.ts +9 -0
  262. package/dist/record/volume-params.d.ts.map +1 -0
  263. package/dist/recovery/render-system-candidate.d.ts +10 -0
  264. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  265. package/dist/reflection/record-owner.d.ts.map +1 -1
  266. package/dist/render-contract.d.ts +66 -8
  267. package/dist/render-contract.d.ts.map +1 -1
  268. package/dist/render-graph-primitives.d.ts.map +1 -1
  269. package/dist/render-pipeline.d.ts +106 -3
  270. package/dist/render-pipeline.d.ts.map +1 -1
  271. package/dist/render-system-extract-tail.d.ts +3 -2
  272. package/dist/render-system-extract-tail.d.ts.map +1 -1
  273. package/dist/render-system-extract.d.ts +24 -10
  274. package/dist/render-system-extract.d.ts.map +1 -1
  275. package/dist/render-system-presentation.d.ts +23 -0
  276. package/dist/render-system-presentation.d.ts.map +1 -0
  277. package/dist/render-system-producer-roots.d.ts +10 -0
  278. package/dist/render-system-producer-roots.d.ts.map +1 -0
  279. package/dist/render-system-residency.d.ts +12 -0
  280. package/dist/render-system-residency.d.ts.map +1 -0
  281. package/dist/render-system.d.ts +26 -15
  282. package/dist/render-system.d.ts.map +1 -1
  283. package/dist/scene/probe-blend.d.ts +27 -0
  284. package/dist/scene/probe-blend.d.ts.map +1 -1
  285. package/dist/scene/render-scene.d.ts +14 -5
  286. package/dist/scene/render-scene.d.ts.map +1 -1
  287. package/dist/ssao-buffers.d.ts +9 -0
  288. package/dist/ssao-buffers.d.ts.map +1 -1
  289. package/dist/surface/dynamic-input.d.ts +133 -0
  290. package/dist/surface/dynamic-input.d.ts.map +1 -0
  291. package/dist/surface/gpu-driven.d.ts +41 -0
  292. package/dist/surface/gpu-driven.d.ts.map +1 -0
  293. package/dist/surface/submission-observation.d.ts +136 -0
  294. package/dist/surface/submission-observation.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  296. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  297. package/dist/temporal/frame.d.ts +7 -0
  298. package/dist/temporal/frame.d.ts.map +1 -1
  299. package/dist/temporal/gpu.d.ts +13 -1
  300. package/dist/temporal/gpu.d.ts.map +1 -1
  301. package/dist/temporal/index.mjs +5 -5
  302. package/dist/temporal/inspection.d.ts.map +1 -1
  303. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  304. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  305. package/dist/temporal/view.d.ts +6 -1
  306. package/dist/temporal/view.d.ts.map +1 -1
  307. package/dist/transmission/single-layer-medium.d.ts +89 -0
  308. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  309. package/dist/typed-render-graph-primitives.d.ts +24 -9
  310. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  311. package/dist/volume/component.d.ts +9 -5
  312. package/dist/volume/component.d.ts.map +1 -1
  313. package/dist/volume/extract.d.ts +1 -1
  314. package/dist/volume/extract.d.ts.map +1 -1
  315. package/dist/volume/inspection.d.ts +2 -0
  316. package/dist/volume/inspection.d.ts.map +1 -1
  317. package/dist/volume/passes.d.ts +4 -1
  318. package/dist/volume/passes.d.ts.map +1 -1
  319. package/dist/volume/resources.d.ts.map +1 -1
  320. package/dist/volume/temporal.d.ts +3 -1
  321. package/dist/volume/temporal.d.ts.map +1 -1
  322. package/package.json +22 -21
  323. package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
  324. package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
  325. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  326. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  327. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  328. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  329. package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
  330. package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
  331. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  332. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  333. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  334. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  335. package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
  336. package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
  337. package/src/__tests__/environment-selection.unit.test.ts +12 -0
  338. package/src/__tests__/factory-contract.integration.test.ts +626 -113
  339. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  340. package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
  341. package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
  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-indirect-raster-evidence.ts +2 -1
  347. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  348. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  349. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  350. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +7 -6
  351. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
  352. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
  353. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  354. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  355. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  356. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  357. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  358. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  359. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  360. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
  361. package/src/__tests__/gpu-scene.unit.test.ts +210 -9
  362. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  363. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  364. package/src/__tests__/instances-store.unit.test.ts +105 -238
  365. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  366. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  367. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  368. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  369. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
  370. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  371. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  372. package/src/__tests__/motion-blur-compute.dawn.test.ts +589 -0
  373. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  374. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  375. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  376. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  377. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
  378. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  379. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
  380. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  381. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  382. package/src/__tests__/public-surface.test-d.ts +8 -0
  383. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  384. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  385. package/src/__tests__/render-error-code-owner.test-d.ts +9 -0
  386. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  387. package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
  388. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  389. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  390. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
  391. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  392. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  393. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +37 -6
  394. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  395. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  396. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  397. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  398. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  399. package/src/__tests__/renderer-frame-transaction.integration.test.ts +33 -11
  400. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  401. package/src/__tests__/shader-manifest-fixture.ts +4 -4
  402. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  403. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  404. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  405. package/src/__tests__/skinned-shadow-caster.test.ts +17 -0
  406. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  407. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  408. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  409. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  410. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  411. package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
  412. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  413. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  414. package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
  415. package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
  416. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  417. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  418. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  419. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  420. package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
  421. package/src/__tests__/temporal-view.unit.test.ts +2 -1
  422. package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
  423. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  424. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  425. package/src/__tests__/volume-optics-oracle.unit.test.ts +7 -3
  426. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
  427. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  428. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  429. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  430. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +558 -68
  431. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
  432. package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
  433. package/src/assembly/analytic-fog-registration.ts +14 -0
  434. package/src/assembly/backend-contract.ts +30 -0
  435. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  436. package/src/assembly/canvas-draw-guard.ts +11 -0
  437. package/src/assembly/cloud-shadow-entry.ts +22 -0
  438. package/src/assembly/dynamic-geometry-host.ts +65 -37
  439. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  440. package/src/assembly/factory.ts +2 -30
  441. package/src/assembly/fxaa-registration.ts +17 -0
  442. package/src/assembly/host-contract.ts +3 -3
  443. package/src/assembly/lod-observation.ts +12 -0
  444. package/src/assembly/material/assembly.ts +25 -13
  445. package/src/assembly/material/pipeline-helpers.ts +53 -12
  446. package/src/assembly/material-shader-policy.ts +55 -0
  447. package/src/assembly/material-shader-prewarm.ts +21 -10
  448. package/src/assembly/motion-blur-registration.ts +17 -0
  449. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  450. package/src/assembly/recovery/renderer-recover.ts +41 -18
  451. package/src/assembly/render-feature-post-processes.ts +54 -0
  452. package/src/assembly/renderer-facade.ts +6 -1
  453. package/src/assembly/renderer-feature-inspection.ts +8 -2
  454. package/src/assembly/renderer-frame-transaction.ts +23 -0
  455. package/src/assembly/renderer-inspection.ts +28 -0
  456. package/src/assembly/skin-palette-owner.ts +1 -1
  457. package/src/assembly/temporal-post-process-prewarm.ts +40 -0
  458. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  459. package/src/assembly/webgpu-ready-contract.ts +8 -3
  460. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  461. package/src/assembly/webgpu-ready.ts +296 -306
  462. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  463. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  464. package/src/assembly/webgpu-renderer.ts +228 -281
  465. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  466. package/src/barrel-distortion.ts +247 -0
  467. package/src/bloom-admission.ts +21 -0
  468. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  469. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  470. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  471. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  472. package/src/cloud/density.ts +600 -0
  473. package/src/cloud/extract.ts +110 -0
  474. package/src/cloud/feature.ts +1810 -0
  475. package/src/cloud/frame-context.ts +42 -0
  476. package/src/cloud/inspection.ts +130 -0
  477. package/src/cloud/optics.ts +285 -0
  478. package/src/cloud/parameters.ts +255 -0
  479. package/src/cloud/resources.ts +122 -0
  480. package/src/cloud/shadow.ts +167 -0
  481. package/src/cloud/temporal.ts +226 -0
  482. package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
  483. package/src/components/atmosphere.ts +4 -0
  484. package/src/components/barrel-distortion.ts +46 -0
  485. package/src/components/camera.ts +66 -10
  486. package/src/components/cloud-layer.ts +47 -0
  487. package/src/components/index.ts +2 -0
  488. package/src/components/instances.ts +18 -45
  489. package/src/components/mesh-filter.ts +11 -9
  490. package/src/components/motion-blur.ts +1 -0
  491. package/src/components/sprite-instances.ts +1 -1
  492. package/src/construct-renderer.ts +1 -1
  493. package/src/device/gpu-residency.ts +56 -12
  494. package/src/dynamic-geometry.ts +12 -1
  495. package/src/environment/analytic-fog.ts +44 -0
  496. package/src/environment/background.ts +2 -2
  497. package/src/errors/cloud.ts +103 -0
  498. package/src/errors/render.ts +58 -8
  499. package/src/examples/single-layer-medium-surface.ts +59 -0
  500. package/src/extract/camera.ts +35 -8
  501. package/src/extract/contracts.ts +12 -0
  502. package/src/extract/environment.ts +4 -0
  503. package/src/features/barrel-distortion.ts +172 -0
  504. package/src/features/error-reporting.ts +98 -0
  505. package/src/features/host.ts +138 -24
  506. package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
  507. package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
  508. package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
  509. package/src/features/motion-blur/motion-blur-params.ts +70 -2
  510. package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
  511. package/src/features/plan.ts +33 -8
  512. package/src/features/prepared-gpu-work.ts +86 -35
  513. package/src/features/render-graph-compute.ts +13 -5
  514. package/src/features/render-graph-contribution.ts +11 -0
  515. package/src/features/render-graph-raster.ts +45 -3
  516. package/src/features/targets.ts +66 -0
  517. package/src/features/types.ts +47 -0
  518. package/src/fullscreen-post-process-pass.ts +41 -9
  519. package/src/gpu-dirty-ranges.ts +48 -0
  520. package/src/gpu-driven/batch-topology.ts +53 -0
  521. package/src/gpu-driven/material-artifacts.ts +35 -32
  522. package/src/gpu-driven/prepared-draw.ts +27 -14
  523. package/src/gpu-driven/production-raster-material.ts +1894 -0
  524. package/src/gpu-driven/production-raster.ts +904 -787
  525. package/src/gpu-driven/resource-allocation.ts +142 -0
  526. package/src/gpu-driven/shadow-ownership.ts +71 -0
  527. package/src/gpu-driven/view-gpu.ts +181 -10
  528. package/src/gpu-scene.ts +259 -101
  529. package/src/hdrp-buffers.ts +4 -3
  530. package/src/ibl/skylight-bind-group.ts +49 -7
  531. package/src/index.ts +228 -9
  532. package/src/inspection-types.ts +222 -2
  533. package/src/instance-buffer-cache.ts +4 -4
  534. package/src/instances.ts +151 -492
  535. package/src/pbr-pipeline.ts +219 -13
  536. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  537. package/src/pipeline/standard-forward-lane.ts +313 -57
  538. package/src/pipeline/standard-output/graph.ts +8 -2
  539. package/src/pipeline/standard-output/types.ts +12 -1
  540. package/src/pipeline/standard-pipeline.ts +291 -18
  541. package/src/pipeline/standard-post.ts +397 -102
  542. package/src/pipeline-builder.ts +1 -1
  543. package/src/pipeline-spec.ts +5 -5
  544. package/src/plugin.ts +4 -0
  545. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  546. package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
  547. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  548. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  549. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  550. package/src/record/__tests__/temporal-payload.unit.test.ts +3 -2
  551. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  552. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  553. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  554. package/src/record/barrel-distortion-frame.ts +110 -0
  555. package/src/record/dynamic-geometry-consumption.ts +39 -9
  556. package/src/record/fold-buckets.ts +852 -0
  557. package/src/record/fold-instance-buffer.ts +51 -0
  558. package/src/record/frame-lighting.ts +36 -2
  559. package/src/record/frame-snapshot.ts +44 -4
  560. package/src/record/frame-targets.ts +10 -6
  561. package/src/record/frame.ts +373 -1099
  562. package/src/record/gpu-draw-receipts.ts +38 -0
  563. package/src/record/gpu-timing.ts +48 -5
  564. package/src/record/main-pass-geometry.ts +281 -83
  565. package/src/record/main-pass-material.ts +66 -4
  566. package/src/record/main-pass-sprite-draws.ts +13 -66
  567. package/src/record/main-pass.ts +156 -20
  568. package/src/record/mesh-ssbo.ts +43 -6
  569. package/src/record/motion-blur-receipt.ts +91 -0
  570. package/src/record/probe-blend-buffer.ts +180 -0
  571. package/src/record/recovery-pipeline.ts +35 -3
  572. package/src/record/render-context.ts +51 -31
  573. package/src/record/shadow-pass.ts +36 -2
  574. package/src/record/skybox-post-pass.ts +150 -200
  575. package/src/record/typed-frame-graph.ts +824 -44
  576. package/src/record/view-ubo.ts +26 -3
  577. package/src/record/volume-params.ts +225 -0
  578. package/src/recovery/render-system-candidate.ts +257 -52
  579. package/src/reflection/record-owner.ts +7 -3
  580. package/src/render-contract.ts +71 -8
  581. package/src/render-graph-primitives.ts +7 -1
  582. package/src/render-pipeline.ts +136 -1
  583. package/src/render-system-extract-tail.ts +72 -60
  584. package/src/render-system-extract.ts +117 -87
  585. package/src/render-system-presentation.ts +56 -0
  586. package/src/render-system-producer-roots.ts +96 -0
  587. package/src/render-system-residency.ts +159 -0
  588. package/src/render-system.ts +601 -482
  589. package/src/scene/probe-blend.ts +96 -4
  590. package/src/scene/render-scene.ts +431 -281
  591. package/src/ssao-buffers.ts +95 -2
  592. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  593. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  594. package/src/surface/dynamic-input.ts +658 -0
  595. package/src/surface/gpu-driven.ts +147 -0
  596. package/src/surface/submission-observation.ts +517 -0
  597. package/src/systems/skin-palette-allocator.ts +4 -1
  598. package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
  599. package/src/temporal/frame-coordinator.ts +8 -1
  600. package/src/temporal/frame.ts +20 -0
  601. package/src/temporal/gpu.ts +101 -17
  602. package/src/temporal/inspection.ts +7 -1
  603. package/src/temporal/standard-scene-data.ts +5 -0
  604. package/src/temporal/target-coverage-attachment.ts +4 -0
  605. package/src/temporal/view.ts +13 -2
  606. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  607. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  608. package/src/transmission/single-layer-medium.ts +322 -0
  609. package/src/typed-render-graph-primitives.ts +191 -50
  610. package/src/volume/component.ts +10 -10
  611. package/src/volume/extract.ts +11 -5
  612. package/src/volume/inspection.ts +3 -0
  613. package/src/volume/passes.ts +95 -8
  614. package/src/volume/resources.ts +2 -1
  615. package/src/volume/temporal.ts +11 -0
  616. package/dist/chunk-4NNZQCL3.mjs.map +0 -1
  617. package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
  618. package/dist/chunk-DRR7D3KX.mjs.map +0 -1
  619. package/dist/chunk-GWCEMDVR.mjs.map +0 -1
  620. package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
  621. package/dist/chunk-JRIPCMYC.mjs.map +0 -1
  622. package/dist/chunk-LULCA3OF.mjs +0 -1713
  623. package/dist/chunk-LULCA3OF.mjs.map +0 -1
  624. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
@@ -1,9 +1,10 @@
1
1
  import { TRANSPARENT_SORT_MODE_LAYER_Z, TRANSPARENT_SORT_MODE_LAYER_Y } from './chunk-RXZ3RGOU.mjs';
2
- import { DEFAULT_CLUSTER_GRID, DEFAULT_STANDARD_PROFILE, createIblKernelCache, MAX_LIGHTS, CLUSTER_GRID_STRIDE_U32, LIGHT_INDEX_LIST_CAPACITY, createStandardClusterLayout } from './chunk-S665NJNF.mjs';
2
+ import { DEFAULT_CLUSTER_GRID, DEFAULT_STANDARD_PROFILE, createIblKernelCache, MAX_LIGHTS, CLUSTER_GRID_STRIDE_U32, LIGHT_INDEX_LIST_CAPACITY, createStandardClusterLayout } from './chunk-OCDLEI6I.mjs';
3
3
  import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from './chunk-BLXGONR2.mjs';
4
- import { GPU_SHADER_STAGE_COMPUTE, GPU_BUFFER_USAGE_STORAGE, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM, createHdrpBindGroupLayoutDescriptor, COOKIE_MATRIX_BYTES, IES_SLICE_WIDTH, IES_SLICE_HEIGHT, COOKIE_SLICE_SIZE, GPU_SHADER_STAGE_VERTEX, GPU_SHADER_STAGE_FRAGMENT, GPU_BUFFER_USAGE_INDEX, GPU_BUFFER_USAGE_VERTEX, isStandardPbrMaterialShader, GPU_BUFFER_USAGE_MAP_READ, pbrSkinMeshDynamicOffsets, instanceCollectionCacheKey, worldEntityKey, gpuDrivenShadowDrawKey, SHADOW_CASTER_SHADER_ID, shadowCasterVariantSet, buildPbrMaterialUserRegionEntries, buildBindGroupLayoutDescriptor, GPU_BUFFER_USAGE_COPY_SRC, GPU_BUFFER_USAGE_INDIRECT, EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES, gpuDrivenSourceDrawItemIndex, matchPass, createPbrSkinMeshBindGroupEntries, physicalTextureFields, isCanonicalStandardPbrMaterialShader, getOpaqueResourceIdentity, resolveRenderTargetMaterialSource, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, isStandardPbrSkinMaterialShader, SKIN_MATERIAL_SHADER_ID, PROBE_BLEND_RECORD_BYTE_SIZE, gpuDrivenDrawKey, probeBlendRecordOffset, PROBE_BLEND_RECORD_STRIDE, materialBindGroupLayoutIdentity } from './chunk-DRR7D3KX.mjs';
5
- import { GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, GPU_TEXTURE_USAGE_COPY_SRC, VertexColorVariantConflictError, EquirectProjectionFailedError, SHADOW_ATLAS_DEFAULT_LAYERS, SHADOW_ATLAS_DEFAULT_FACE_SIZE, ShadowAtlas, PointShadowAtlasUninitializedError, PointShadowAtlasBoundsViolationError, StandardClusterTransportUnavailableError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_TEXTURE_BINDING, createVisibilityBudget, instanceUploadRangesForResident, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, StandardLightBudgetExceededError, RendererOperationError, VideoUploadUnsupportedError, StandardClusterIndexOverflowError, FXAA_POST_PROCESS_ID } from './chunk-6TFBXLRJ.mjs';
4
+ import { GPU_SHADER_STAGE_COMPUTE, GPU_BUFFER_USAGE_STORAGE, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM, createHdrpBindGroupLayoutDescriptor, COOKIE_MATRIX_BYTES, IES_SLICE_WIDTH, IES_SLICE_HEIGHT, COOKIE_SLICE_SIZE, GPU_SHADER_STAGE_VERTEX, GPU_SHADER_STAGE_FRAGMENT, GPU_BUFFER_USAGE_INDEX, GPU_BUFFER_USAGE_VERTEX, isStandardPbrMaterialShader, probeBlendRecordOffset, worldEntityKey, instanceCollectionCacheKey, PROBE_BLEND_RECORD_BYTE_SIZE, GPU_BUFFER_USAGE_MAP_READ, getOpaqueResourceIdentity, pbrSkinMeshDynamicOffsets, gpuDrivenShadowDrawKey, SHADOW_CASTER_SHADER_ID, shadowCasterVariantSet, buildPbrMaterialUserRegionEntries, buildBindGroupLayoutDescriptor, GPU_BUFFER_USAGE_COPY_SRC, GPU_BUFFER_USAGE_INDIRECT, EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES, PROBE_BLEND_RECORD_STRIDE, gpuDrivenSourceDrawItemIndex, matchPass, createPbrSkinMeshBindGroupEntries, physicalTextureFields, isCanonicalStandardPbrMaterialShader, resolveRenderTargetMaterialSource, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, isStandardPbrSkinMaterialShader, SKIN_MATERIAL_SHADER_ID, gpuDrivenDrawKey, materialBindGroupLayoutIdentity } from './chunk-SHFUFJ5N.mjs';
5
+ import { GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, GPU_TEXTURE_USAGE_COPY_SRC, VertexColorVariantConflictError, EquirectProjectionFailedError, SHADOW_ATLAS_DEFAULT_LAYERS, SHADOW_ATLAS_DEFAULT_FACE_SIZE, ShadowAtlas, PointShadowAtlasUninitializedError, PointShadowAtlasBoundsViolationError, StandardClusterTransportUnavailableError, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_TEXTURE_BINDING, instanceUploadRangesForResident, createVisibilityBudget, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, StandardLightBudgetExceededError, RendererOperationError, VideoUploadUnsupportedError, StandardClusterIndexOverflowError, FXAA_POST_PROCESS_ID } from './chunk-WEX45HKH.mjs';
6
6
  import { derive, ok, err as err$1, toShared, ASSET_ERROR_HINTS, deriveTextureLayout, handleSlot, resolveMaterialTextureCoordinates, KNOWN_PASS_KINDS } from '@forgeax/engine-types';
7
+ import { RenderGraphError } from '@forgeax/engine-render-graph';
7
8
  import { ok as ok$1, err, RhiError } from '@forgeax/engine-rhi';
8
9
  import { mat3, vec3, mat4 } from '@forgeax/engine-math';
9
10
  import { deriveVertexLayoutProjection, DEFAULT_VERTEX_ATTRIBUTE_MAP, deriveVertexBufferLayout, deriveVertexBufferLayoutFromProjection } from '@forgeax/engine-geometry';
@@ -11,7 +12,6 @@ import { resolveAssetHandle } from '@forgeax/engine-assets-runtime';
11
12
  import { probeVideoHighPerfUpload, VIDEO_ELEMENT_PROVIDER_KEY } from '@forgeax/engine-graphics-extras';
12
13
  import { DEFAULT_STANDARD_PBR_PARAM_SCHEMA, STANDARD_PIPELINE_PARAM_SCHEMA, GPU_DRIVEN_MATERIAL_ROW_BYTES, findVariantByKey, DEFAULT_MSDF_TEXT_PARAM_SCHEMA, DEFAULT_SPRITE_PARAM_SCHEMA, DEFAULT_UNLIT_PARAM_SCHEMA, STANDARD_PHYSICAL_TEXTURE_FIELDS, STANDARD_TEXTURE_MASK_OVERRIDE } from '@forgeax/engine-shader';
13
14
  import { isCompressedFormat, bytesPerRow, blockParamsForFormat } from '@forgeax/engine-codec';
14
- import { RenderGraphError } from '@forgeax/engine-render-graph';
15
15
 
16
16
  // src/pipeline/render-extent.ts
17
17
  function renderExtentSize(extent, domain) {
@@ -119,6 +119,17 @@ function importRenderPipelineSurface(graph, topology) {
119
119
  }
120
120
  });
121
121
  }
122
+ function renderPipelineCloudHistoryTargets(input) {
123
+ const entries = [
124
+ ["cloud-history-radiance-previous", input.previousRadiance],
125
+ ["cloud-history-radiance-current", input.currentRadiance],
126
+ ["cloud-history-transmittance-previous", input.previousTransmittance],
127
+ ["cloud-history-transmittance-current", input.currentTransmittance],
128
+ ["cloud-history-depth-previous", input.previousDepth],
129
+ ["cloud-history-depth-current", input.currentDepth]
130
+ ];
131
+ return entries.map(([name, target]) => ({ name, kind: "scene-color", ...target }));
132
+ }
122
133
  var STORAGE_BUFFER_MIN_REQUIRED = 4;
123
134
  var BYTES_PER_DIRECT_LIGHT_SLOT = 80;
124
135
  var DirectLightSlotKind = {
@@ -449,7 +460,7 @@ var passKindPolicyTable = {
449
460
  },
450
461
  defaultDepthOps: void 0
451
462
  },
452
- "bloom-bright": {
463
+ "bloom-downsample": {
453
464
  shape: "color-only",
454
465
  defaultColorOps: {
455
466
  loadOp: "clear",
@@ -458,7 +469,7 @@ var passKindPolicyTable = {
458
469
  },
459
470
  defaultDepthOps: void 0
460
471
  },
461
- "bloom-blur": {
472
+ "bloom-upsample": {
462
473
  shape: "color-only",
463
474
  defaultColorOps: {
464
475
  loadOp: "clear",
@@ -780,7 +791,7 @@ function buildSpecConstTable(ldrViewFormat) {
780
791
  // has sampleCount=4. Both use empty vertexLayout (fullscreen triangle, no
781
792
  // attributes) and cullMode='none' (forward cull for fullscreen-quad passthrough).
782
793
  //
783
- // Shadow-probe / fxaa / bloom 4-stage / SSAO 2-stage are lazy-build — not in
794
+ // Shadow-probe / fxaa / Bloom 10-pass / SSAO 2-stage are lazy-build — not in
784
795
  // SPEC_CONST_TABLE (R-D4 decision: only entries that are always-present on
785
796
  // every boot).
786
797
  // tonemap LDR S1 (writes to runtime-resolved swap-chain LDR view format)
@@ -853,16 +864,34 @@ var MESH_UBO_FULL_ARRAY_BYTES = 112 * 128;
853
864
  var INSTANCE_UBO_FULL_ARRAY_BYTES = 80 * 128;
854
865
  var MAX_UNIFORM_INSTANCES = 128;
855
866
  var INSTANCE_STORAGE_STRIDE_FLOATS = 32;
856
- function packInstanceStorageBuffer(transforms) {
867
+ function hasStableGenerationColumn(generations, count) {
868
+ if (generations === void 0 || generations.length !== count) return false;
869
+ const seen = /* @__PURE__ */ new Set();
870
+ for (const generation of generations) {
871
+ if (generation === 0 || seen.has(generation)) return false;
872
+ seen.add(generation);
873
+ }
874
+ return true;
875
+ }
876
+ function packInstanceStorageBuffer(transforms, previousTransforms = transforms, generations, previousGenerations) {
857
877
  const count = Math.floor(transforms.length / 16);
858
878
  const out = new Float32Array(count * INSTANCE_STORAGE_STRIDE_FLOATS);
879
+ const previousCount = Math.floor(previousTransforms.length / 16);
880
+ const generationInput = generations !== void 0 || previousGenerations !== void 0;
881
+ const identityProof = hasStableGenerationColumn(generations, count) && hasStableGenerationColumn(previousGenerations, previousCount);
882
+ const previousIndexByGeneration = identityProof ? new Map(
883
+ Array.from(previousGenerations ?? [], (generation, index) => [generation, index])
884
+ ) : void 0;
859
885
  for (let i = 0; i < count; i++) {
860
886
  const sourceBase = i * 16;
861
887
  const targetBase = i * INSTANCE_STORAGE_STRIDE_FLOATS;
888
+ const previousIndex = identityProof ? previousIndexByGeneration?.get(generations?.[i] ?? 0) : !generationInput && previousCount === count ? i : void 0;
889
+ const sameIdentity = previousIndex !== void 0 && previousIndex < previousCount;
890
+ const previousBase = (previousIndex ?? i) * 16;
862
891
  for (let k = 0; k < 16; k++) {
863
892
  const value = transforms[sourceBase + k] ?? 0;
864
893
  out[targetBase + k] = value;
865
- out[targetBase + 16 + k] = value;
894
+ out[targetBase + 16 + k] = sameIdentity ? previousTransforms[previousBase + k] ?? value : value;
866
895
  }
867
896
  }
868
897
  return out;
@@ -1008,6 +1037,7 @@ function uploadMeshSsboBatch(queue, meshStorageBuffer, validatedOrdered, foldDis
1008
1037
  _meshSsboScratchFloats[slot + 38] = 1;
1009
1038
  _meshSsboScratchFloats[slot + 43] = 1;
1010
1039
  _meshSsboScratchFloats[slot + 44] = 1;
1040
+ _meshSsboScratchFloats[slot + 45] = 1;
1011
1041
  } else {
1012
1042
  const worldFromLocal = entry.source.transform.world;
1013
1043
  for (let k = 0; k < 16; k++) _meshSsboScratchFloats[slot + k] = worldFromLocal[k] ?? 0;
@@ -1034,6 +1064,7 @@ function uploadMeshSsboBatch(queue, meshStorageBuffer, validatedOrdered, foldDis
1034
1064
  }
1035
1065
  }
1036
1066
  _meshSsboScratchFloats[slot + 44] = entry.source.temporal?.reactive === true || reactiveMaterial ? 1 : 0;
1067
+ _meshSsboScratchFloats[slot + 45] = entry.source.temporal?.motionValid === false ? 0 : 1;
1037
1068
  }
1038
1069
  }
1039
1070
  if (neededBytes > 0) {
@@ -1229,10 +1260,35 @@ function generateSsaoNoise(seed = 0) {
1229
1260
  var BYTES_PER_KERNEL_ELEMENT = 16;
1230
1261
  var UNIFORM_BYTES = 256;
1231
1262
  var fallbackCache = /* @__PURE__ */ new WeakMap();
1263
+ function destroyBuffer(runtime, device, buffer) {
1264
+ const destroyed = device.destroyBuffer(buffer);
1265
+ if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
1266
+ }
1267
+ function destroyTexture(runtime, device, texture) {
1268
+ const destroyed = device.destroyTexture(texture);
1269
+ if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
1270
+ }
1271
+ function retireSsaoResources(device, release) {
1272
+ const queue = device.queue;
1273
+ if (typeof queue.onSubmittedWorkDone === "function") {
1274
+ try {
1275
+ void queue.onSubmittedWorkDone().then(release, release);
1276
+ return;
1277
+ } catch {
1278
+ }
1279
+ }
1280
+ release();
1281
+ }
1282
+ function destroySsaoFallbackResources(runtime, resources) {
1283
+ destroyTexture(runtime, resources.device, resources.texture);
1284
+ }
1232
1285
  function getOrCreateSsaoFallbackTexture(runtime) {
1233
1286
  const cached = fallbackCache.get(runtime);
1234
1287
  if (cached !== void 0 && cached.device === runtime.device) return cached;
1235
- if (cached !== void 0) fallbackCache.delete(runtime);
1288
+ if (cached !== void 0) {
1289
+ fallbackCache.delete(runtime);
1290
+ retireSsaoResources(cached.device, () => destroySsaoFallbackResources(runtime, cached));
1291
+ }
1236
1292
  const device = runtime.device;
1237
1293
  const texRes = device.createTexture({
1238
1294
  label: "hdrp-ssao-fallback-white",
@@ -1261,6 +1317,7 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1261
1317
  );
1262
1318
  if (!writeRes.ok) {
1263
1319
  runtime.errorRegistry.fire(writeRes.error);
1320
+ destroyTexture(runtime, device, texRes.value);
1264
1321
  return null;
1265
1322
  }
1266
1323
  const viewRes = device.createTextureView(texRes.value, {
@@ -1275,6 +1332,7 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1275
1332
  });
1276
1333
  if (!viewRes.ok) {
1277
1334
  runtime.errorRegistry.fire(viewRes.error);
1335
+ destroyTexture(runtime, device, texRes.value);
1278
1336
  return null;
1279
1337
  }
1280
1338
  const samplerRes = device.createSampler({
@@ -1288,6 +1346,7 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1288
1346
  });
1289
1347
  if (!samplerRes.ok) {
1290
1348
  runtime.errorRegistry.fire(samplerRes.error);
1349
+ destroyTexture(runtime, device, texRes.value);
1291
1350
  return null;
1292
1351
  }
1293
1352
  const resources = {
@@ -1300,10 +1359,35 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1300
1359
  return resources;
1301
1360
  }
1302
1361
  var cache = /* @__PURE__ */ new WeakMap();
1362
+ function destroySsaoBufferResources(runtime, buffers) {
1363
+ for (const buffer of [buffers.kernelBuffer, buffers.uniformBuffer]) {
1364
+ destroyBuffer(runtime, buffers.device, buffer);
1365
+ }
1366
+ destroyTexture(runtime, buffers.device, buffers.noiseTexture);
1367
+ }
1368
+ function destroyCreatedSsaoResources(runtime, device, buffers, textures) {
1369
+ for (const buffer of buffers) destroyBuffer(runtime, device, buffer);
1370
+ for (const texture of textures) destroyTexture(runtime, device, texture);
1371
+ }
1372
+ function resetSsaoResources(runtime) {
1373
+ const buffers = cache.get(runtime);
1374
+ if (buffers !== void 0) {
1375
+ cache.delete(runtime);
1376
+ retireSsaoResources(buffers.device, () => destroySsaoBufferResources(runtime, buffers));
1377
+ }
1378
+ const fallback = fallbackCache.get(runtime);
1379
+ if (fallback !== void 0) {
1380
+ fallbackCache.delete(runtime);
1381
+ retireSsaoResources(fallback.device, () => destroySsaoFallbackResources(runtime, fallback));
1382
+ }
1383
+ }
1303
1384
  function getOrCreateSsaoBuffers(runtime) {
1304
1385
  const cached = cache.get(runtime);
1305
1386
  if (cached !== void 0 && cached.device === runtime.device) return cached;
1306
- if (cached !== void 0) cache.delete(runtime);
1387
+ if (cached !== void 0) {
1388
+ cache.delete(runtime);
1389
+ retireSsaoResources(cached.device, () => destroySsaoBufferResources(runtime, cached));
1390
+ }
1307
1391
  const device = runtime.device;
1308
1392
  const kernelSamples = generateSsaoKernel();
1309
1393
  const kernelData = new Float32Array(SSAO_KERNEL_SAMPLE_COUNT * 4);
@@ -1327,6 +1411,7 @@ function getOrCreateSsaoBuffers(runtime) {
1327
1411
  const kernelWriteRes = device.queue.writeBuffer(kernelBufferRes.value, 0, kernelData);
1328
1412
  if (!kernelWriteRes.ok) {
1329
1413
  runtime.errorRegistry.fire(kernelWriteRes.error);
1414
+ destroyBuffer(runtime, device, kernelBufferRes.value);
1330
1415
  return null;
1331
1416
  }
1332
1417
  const noiseData = generateSsaoNoise();
@@ -1349,6 +1434,7 @@ function getOrCreateSsaoBuffers(runtime) {
1349
1434
  });
1350
1435
  if (!noiseTexRes.ok) {
1351
1436
  runtime.errorRegistry.fire(noiseTexRes.error);
1437
+ destroyBuffer(runtime, device, kernelBufferRes.value);
1352
1438
  return null;
1353
1439
  }
1354
1440
  const noiseCopyRes = device.queue.writeTexture(
@@ -1363,6 +1449,7 @@ function getOrCreateSsaoBuffers(runtime) {
1363
1449
  );
1364
1450
  if (!noiseCopyRes.ok) {
1365
1451
  runtime.errorRegistry.fire(noiseCopyRes.error);
1452
+ destroyCreatedSsaoResources(runtime, device, [kernelBufferRes.value], [noiseTexRes.value]);
1366
1453
  return null;
1367
1454
  }
1368
1455
  const uniformBufRes = device.createBuffer({
@@ -1373,6 +1460,7 @@ function getOrCreateSsaoBuffers(runtime) {
1373
1460
  });
1374
1461
  if (!uniformBufRes.ok) {
1375
1462
  runtime.errorRegistry.fire(uniformBufRes.error);
1463
+ destroyCreatedSsaoResources(runtime, device, [kernelBufferRes.value], [noiseTexRes.value]);
1376
1464
  return null;
1377
1465
  }
1378
1466
  const buffers = {
@@ -1669,7 +1757,7 @@ function createStandardSurfaceLightingBindGroup(runtime, layout, grid, ssaoOptio
1669
1757
  }
1670
1758
  return result.value;
1671
1759
  }
1672
- function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssaoOptions = { enabled: false }) {
1760
+ function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssaoOptions = { enabled: false }, meshBindingBytes = MESH_PER_ENTITY_STRIDE) {
1673
1761
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
1674
1762
  if (fallback === null) return null;
1675
1763
  const ssaoTexView = ssaoOptions.enabled ? ssaoOptions.ssaoBlurredView : fallback.view;
@@ -1685,7 +1773,7 @@ function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssa
1685
1773
  value: {
1686
1774
  buffer: meshStorageBuffer,
1687
1775
  offset: 0,
1688
- size: MESH_PER_ENTITY_STRIDE
1776
+ size: meshBindingBytes
1689
1777
  }
1690
1778
  }
1691
1779
  },
@@ -1698,17 +1786,16 @@ function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssa
1698
1786
  }
1699
1787
  return result.value;
1700
1788
  }
1701
- function createHdrpSkinUnifiedBindGroup(runtime, hdrpBuffers, layout, meshStorageBuffer, paletteBuffer, paletteBindingWindowBytes, ssaoOptions = { enabled: false }) {
1789
+ function createHdrpSkinUnifiedBindGroup(runtime, hdrpBuffers, layout, meshStorageBuffer, paletteBuffer, paletteBindingWindowBytes, ssaoOptions = { enabled: false }, meshBindingBytes = MESH_PER_ENTITY_STRIDE) {
1702
1790
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
1703
1791
  if (fallback === null) return null;
1704
- const meshSize = MESH_PER_ENTITY_STRIDE;
1705
1792
  const result = runtime.device.createBindGroup({
1706
1793
  label: "hdrp-skin-unified-bg-group2",
1707
1794
  layout,
1708
1795
  entries: [
1709
1796
  ...createPbrSkinMeshBindGroupEntries(
1710
1797
  meshStorageBuffer,
1711
- meshSize,
1798
+ meshBindingBytes,
1712
1799
  paletteBuffer,
1713
1800
  paletteBindingWindowBytes
1714
1801
  ),
@@ -2425,7 +2512,7 @@ function computeProjectionMatrix(camera) {
2425
2512
  }
2426
2513
  return proj;
2427
2514
  }
2428
- var VIEW_UNIFORM_BYTES = 960;
2515
+ var VIEW_UNIFORM_BYTES = 1024;
2429
2516
  var POINTS_LINES_VIEW_BYTES = 160;
2430
2517
  var POINTS_LINES_VIEW_SLOT_STRIDE = 256;
2431
2518
  var POINTS_LINES_VIEW_SLOT_COUNT = 1024;
@@ -2489,7 +2576,7 @@ function writePointsLinesViewUbo(queue, buffer, camera, width, height, model, st
2489
2576
  const uploaded = queue.writeBuffer(buffer, byteOffset, payload);
2490
2577
  if (!uploaded.ok) throw uploaded.error;
2491
2578
  }
2492
- function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShadowSnapshots, temporalOrOffset, projectorSpotIndex) {
2579
+ function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShadowSnapshots, temporalOrOffset, projectorSpotIndex, cloudShadowProjection) {
2493
2580
  const byteOffset = typeof temporalOrOffset === "number" ? temporalOrOffset : 0;
2494
2581
  const resolvedTemporal = typeof temporalOrOffset === "number" ? void 0 : temporalOrOffset;
2495
2582
  const projMatrix = computeProjectionMatrix(camera);
@@ -2507,7 +2594,7 @@ function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShado
2507
2594
  }
2508
2595
  const mainProjection = mat4.create();
2509
2596
  mat4.multiply(mainProjection, jitteredProjection, viewMatrix);
2510
- const VIEW_PAYLOAD_FLOATS = 240;
2597
+ const VIEW_PAYLOAD_FLOATS = 256;
2511
2598
  const viewPayload = new Float32Array(VIEW_PAYLOAD_FLOATS);
2512
2599
  for (let i = 0; i < 16; i++) viewPayload[i] = mainProjection[i] ?? 0;
2513
2600
  viewPayload[16] = light.direction[0] ?? 0;
@@ -2556,6 +2643,20 @@ function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShado
2556
2643
  viewPayload[238] = ssr.maxRoughness;
2557
2644
  viewPayload[239] = 1;
2558
2645
  }
2646
+ if (cloudShadowProjection !== void 0) {
2647
+ viewPayload[240] = cloudShadowProjection.origin[0] ?? 0;
2648
+ viewPayload[241] = cloudShadowProjection.origin[1] ?? 0;
2649
+ viewPayload[242] = cloudShadowProjection.origin[2] ?? 0;
2650
+ viewPayload[244] = cloudShadowProjection.right[0] ?? 0;
2651
+ viewPayload[245] = cloudShadowProjection.right[1] ?? 0;
2652
+ viewPayload[246] = cloudShadowProjection.right[2] ?? 0;
2653
+ viewPayload[248] = cloudShadowProjection.up[0] ?? 0;
2654
+ viewPayload[249] = cloudShadowProjection.up[1] ?? 0;
2655
+ viewPayload[250] = cloudShadowProjection.up[2] ?? 0;
2656
+ viewPayload[252] = cloudShadowProjection.range;
2657
+ viewPayload[253] = cloudShadowProjection.lowSun ? 0 : 1;
2658
+ viewPayload[254] = cloudShadowProjection.lowSun ? 1 : 0;
2659
+ }
2559
2660
  if (lights.splitPlanes !== void 0) {
2560
2661
  for (let s = 0; s < 4; s++) {
2561
2662
  for (let lane = 0; lane < 4; lane++) {
@@ -2665,6 +2766,7 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2665
2766
  const b5View = atlasViewMaybe !== null ? atlasViewMaybe : pipelineState.shadowAtlasFallbackTextureView;
2666
2767
  const graphSpotShadowView = graphTargets?.spotShadow;
2667
2768
  const b8View = graphSpotShadowView !== void 0 ? graphSpotShadowView : pipelineState.shadowFallbackTextureView;
2769
+ const cloudShadowView = graphTargets?.cloudShadow ?? pipelineState.defaultWhiteTextureView;
2668
2770
  const extendedLighting = pipelineState.extendedLightingAvailable ?? true;
2669
2771
  const iesProfileTextureView = pipelineState.iesProfileTextureView;
2670
2772
  const cookieTextureView = pipelineState.cookieTextureView;
@@ -2696,6 +2798,7 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2696
2798
  extendedLightingResources.cookieMatrixBuffer
2697
2799
  ] : [];
2698
2800
  const projectorAvailable = pipelineState.projectorAvailable !== false;
2801
+ const lowLimitCloudBindings = !extendedLighting && !projectorAvailable;
2699
2802
  const b11View = graphTargets?.projector ?? pipelineState.defaultWhiteTextureView;
2700
2803
  const b12Sampler = graphTargets?.projectorSampler ?? pipelineState.defaultSampler;
2701
2804
  viewBindGroup = getOrCreateFromChain(
@@ -2709,7 +2812,8 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2709
2812
  b8View,
2710
2813
  ...extendedLightingViews,
2711
2814
  ...extendedLightingResources === void 0 && projectorAvailable ? [b11View, b12Sampler] : [],
2712
- pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer
2815
+ pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
2816
+ ...lowLimitCloudBindings ? [] : [cloudShadowView, pipelineState.defaultSampler]
2713
2817
  ],
2714
2818
  "view-main",
2715
2819
  () => {
@@ -2791,8 +2895,20 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2791
2895
  }
2792
2896
  },
2793
2897
  ...extendedLightingResources === void 0 && projectorAvailable ? [
2794
- { binding: 11, resource: { kind: "textureView", value: b11View } },
2795
- { binding: 12, resource: { kind: "sampler", value: b12Sampler } }
2898
+ {
2899
+ binding: 11,
2900
+ resource: {
2901
+ kind: "textureView",
2902
+ value: b11View
2903
+ }
2904
+ },
2905
+ {
2906
+ binding: 12,
2907
+ resource: {
2908
+ kind: "sampler",
2909
+ value: b12Sampler
2910
+ }
2911
+ }
2796
2912
  ] : [],
2797
2913
  ...extendedLightingResources !== void 0 ? [
2798
2914
  {
@@ -2840,7 +2956,23 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2840
2956
  }
2841
2957
  }
2842
2958
  }
2843
- ] : []
2959
+ ] : [],
2960
+ ...lowLimitCloudBindings ? [] : [
2961
+ {
2962
+ binding: 16,
2963
+ resource: {
2964
+ kind: "textureView",
2965
+ value: cloudShadowView
2966
+ }
2967
+ },
2968
+ {
2969
+ binding: 17,
2970
+ resource: {
2971
+ kind: "sampler",
2972
+ value: pipelineState.defaultSampler
2973
+ }
2974
+ }
2975
+ ]
2844
2976
  // feat-20260625-spot-light-shadow-mapping w25: the per-spot
2845
2977
  // fragment-read lightViewProj matrices fold into the View UBO
2846
2978
  // (binding 0, `view.spotLightViewProj`) — no standalone binding 9
@@ -4275,6 +4407,42 @@ var GpuTexture = class {
4275
4407
  return r;
4276
4408
  }
4277
4409
  };
4410
+
4411
+ // src/record/fold-instance-buffer.ts
4412
+ function resolveFoldInstanceBuffer(c, bucket, headIndex) {
4413
+ const { runtime, frameState } = c;
4414
+ const key = -1 - ((bucket.materialHandle & 65535) << 16 | headIndex & 65535);
4415
+ const uniform = runtime.device.caps.storageBuffer === false;
4416
+ const payload = uniform ? bucket.transforms : packInstanceStorageBuffer(bucket.transforms);
4417
+ let resident = frameState.instanceBuffers.get(key);
4418
+ if (resident === void 0 || resident.uploadedByteLength !== payload.byteLength) {
4419
+ const created = runtime.device.createBuffer({
4420
+ size: payload.byteLength,
4421
+ usage: (uniform ? GPU_BUFFER_USAGE_UNIFORM : GPU_BUFFER_USAGE_STORAGE) | GPU_BUFFER_USAGE_COPY_DST,
4422
+ mappedAtCreation: false
4423
+ });
4424
+ if (!created.ok) {
4425
+ runtime.errorRegistry.fire(created.error);
4426
+ return null;
4427
+ }
4428
+ if (resident !== void 0 && !resident.buffer.isDestroyed) {
4429
+ const destroyed = resident.buffer.destroy();
4430
+ if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
4431
+ }
4432
+ resident = {
4433
+ buffer: new GpuBuffer(runtime.device, created.value),
4434
+ uploadedArchVersion: bucket.bucketSize,
4435
+ uploadedByteLength: payload.byteLength
4436
+ };
4437
+ frameState.instanceBuffers.set(key, resident);
4438
+ }
4439
+ const written = runtime.device.queue.writeBuffer(resident.buffer.handle, 0, payload);
4440
+ if (!written.ok) {
4441
+ runtime.errorRegistry.fire(written.error);
4442
+ return null;
4443
+ }
4444
+ return resident.buffer.handle;
4445
+ }
4278
4446
  var STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES = 18;
4279
4447
  function isOrdinaryMaterialVariant(variant) {
4280
4448
  return variant.defines.COVERAGE_ONLY !== true;
@@ -4383,7 +4551,7 @@ function deviceOptionsForAdapter(adapter, options) {
4383
4551
 
4384
4552
  // src/ibl/skylight-bind-group.ts
4385
4553
  var FALLBACK_BYTES_PER_ROW = 256;
4386
- function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmission, textureInjections = []) {
4554
+ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmission, textureInjections = [], surfaceMedium) {
4387
4555
  const iblStart = materialEntries.length;
4388
4556
  const result = [
4389
4557
  ...materialEntries,
@@ -4430,6 +4598,35 @@ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmis
4430
4598
  resource: { kind: "textureView", value: transmissionView }
4431
4599
  }
4432
4600
  );
4601
+ if (surfaceMedium !== void 0) {
4602
+ const surfaceStart = result.length;
4603
+ result.push(
4604
+ {
4605
+ binding: surfaceStart,
4606
+ resource: { kind: "sampler", value: surfaceMedium.rawDepthSampler }
4607
+ },
4608
+ {
4609
+ binding: surfaceStart + 1,
4610
+ resource: { kind: "textureView", value: surfaceMedium.rawDepthView }
4611
+ },
4612
+ {
4613
+ binding: surfaceStart + 2,
4614
+ resource: { kind: "sampler", value: surfaceMedium.nearestLayerSampler }
4615
+ },
4616
+ {
4617
+ binding: surfaceStart + 3,
4618
+ resource: { kind: "textureView", value: surfaceMedium.nearestLayerView }
4619
+ },
4620
+ {
4621
+ binding: surfaceStart + 4,
4622
+ resource: { kind: "sampler", value: surfaceMedium.nearestDepthSampler }
4623
+ },
4624
+ {
4625
+ binding: surfaceStart + 5,
4626
+ resource: { kind: "textureView", value: surfaceMedium.nearestDepthView }
4627
+ }
4628
+ );
4629
+ }
4433
4630
  const physicalStart = 26;
4434
4631
  for (let index = 0; index < textureInjections.length; index += 1) {
4435
4632
  const resource = textureInjections[index];
@@ -4446,13 +4643,15 @@ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmis
4446
4643
  }
4447
4644
  );
4448
4645
  }
4449
- result.push({
4450
- binding: 47,
4451
- resource: {
4452
- kind: "textureView",
4453
- value: skylight.skylightPrefilterView ?? skylight.prefilterView
4454
- }
4455
- });
4646
+ if (surfaceMedium === void 0) {
4647
+ result.push({
4648
+ binding: 47,
4649
+ resource: {
4650
+ kind: "textureView",
4651
+ value: skylight.skylightPrefilterView ?? skylight.prefilterView
4652
+ }
4653
+ });
4654
+ }
4456
4655
  return result;
4457
4656
  }
4458
4657
  function createSkylightFallback(device, queue) {
@@ -5257,8 +5456,8 @@ function recordIblMaterialBinding(frameState, materialBgl, bindGroup, entries, i
5257
5456
  errors: []
5258
5457
  };
5259
5458
  }
5260
- function isMaterialBgAssemblyCacheHit(cached, material, materialBgl, materialBuffer, skylightResources, materialResourceEpoch, transmissionBackdropView, sceneMaterialBuffer) {
5261
- if (transmissionBackdropView != null) return false;
5459
+ function isMaterialBgAssemblyCacheHit(cached, material, materialBgl, materialBuffer, skylightResources, materialResourceEpoch, transmissionBackdropView, sceneMaterialBuffer, surfaceRawDepthView) {
5460
+ if (transmissionBackdropView != null || surfaceRawDepthView != null) return false;
5262
5461
  return cached?.material === material && cached.materialResourceEpoch === materialResourceEpoch && cached.materialBgl === materialBgl && cached.materialBuffer === materialBuffer && cached.sceneMaterialBuffer === sceneMaterialBuffer && cached.skylightResources.irradianceView === skylightResources.irradianceView && cached.skylightResources.irradianceSampler === skylightResources.irradianceSampler && cached.skylightResources.prefilterView === skylightResources.prefilterView && cached.skylightResources.skylightPrefilterView === skylightResources.skylightPrefilterView && cached.skylightResources.prefilterSampler === skylightResources.prefilterSampler && cached.skylightResources.brdfLutView === skylightResources.brdfLutView && cached.skylightResources.brdfLutSampler === skylightResources.brdfLutSampler && cached.skylightResources.intensityBuffer === skylightResources.intensityBuffer;
5263
5462
  }
5264
5463
  function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWorld = deps.world, materialShaderId = submeshMaterial.materialShaderId) {
@@ -5274,6 +5473,9 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5274
5473
  materialBgShared,
5275
5474
  materialBgAssemblyCache,
5276
5475
  transmissionBackdropView,
5476
+ surfaceRawDepthView,
5477
+ surfaceNearestLayerView,
5478
+ surfaceNearestDepthView,
5277
5479
  bindGroupCounts,
5278
5480
  frameState
5279
5481
  } = deps;
@@ -5283,6 +5485,35 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5283
5485
  const materialCacheKey = smMaterialHandle === void 0 ? void 0 : `${materialWorld.identity}:${smMaterialHandle}:${materialShaderId ?? ""}:${selectedProbe?.probeIndex ?? "sky"}`;
5284
5486
  const smHasVideoFields = (submeshMaterial.videoTextureFields?.size ?? 0) > 0;
5285
5487
  const smShaderId = materialShaderId;
5488
+ const selectedMaterialShaderArtifact = smShaderId === void 0 ? void 0 : runtime.getMaterialShaderArtifact?.(smShaderId);
5489
+ const selectedMediumShader = smShaderId === "forgeax::single-layer-medium" || selectedMaterialShaderArtifact?.receipt?.surface?.model === "single-layer-medium";
5490
+ let surfaceMediumResources;
5491
+ if (selectedMediumShader) {
5492
+ if (surfaceRawDepthView == null) {
5493
+ throw new RhiError({
5494
+ code: "rhi-descriptor-invalid",
5495
+ expected: "single-layer medium material bind group has producer-owned raw depth",
5496
+ hint: "admit the Surface material only from a graph pass with an available raw-depth pair"
5497
+ });
5498
+ }
5499
+ const nearestLayerView = surfaceNearestLayerView ?? transmissionBackdropView;
5500
+ const nearestDepthView = surfaceNearestDepthView ?? pipelineState.shadowFallbackTextureView;
5501
+ if (nearestLayerView == null || pipelineState.surfaceMediumDepthSampler === void 0) {
5502
+ throw new RhiError({
5503
+ code: "rhi-descriptor-invalid",
5504
+ expected: "single-layer medium material bind group has paired nearest resources and depth sampler",
5505
+ hint: "publish the nearest-layer target and the non-filtering raw-depth sampler before recording the Surface pass"
5506
+ });
5507
+ }
5508
+ surfaceMediumResources = {
5509
+ rawDepthSampler: pipelineState.surfaceMediumDepthSampler,
5510
+ rawDepthView: surfaceRawDepthView,
5511
+ nearestLayerSampler: effectiveSkylightResources.prefilterSampler,
5512
+ nearestLayerView,
5513
+ nearestDepthSampler: pipelineState.surfaceMediumDepthSampler,
5514
+ nearestDepthView
5515
+ };
5516
+ }
5286
5517
  const smSchema = (smShaderId !== void 0 ? runtime.getParamSchema?.(smShaderId) : void 0) ?? submeshMaterial.materialParamSchema;
5287
5518
  const smPerShaderBgl = smShaderId !== void 0 ? runtime.getMaterialBindGroupLayout?.(smShaderId, smSchema) : void 0;
5288
5519
  const smMaterialBgl = smPerShaderBgl ?? pipelineState.materialBindGroupLayout;
@@ -5302,7 +5533,8 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5302
5533
  effectiveSkylightResources,
5303
5534
  store.materialResourceEpoch,
5304
5535
  transmissionBackdropView,
5305
- sceneMaterialBuffer
5536
+ sceneMaterialBuffer,
5537
+ surfaceRawDepthView
5306
5538
  )) {
5307
5539
  if (diagnosticsEnabled) {
5308
5540
  recordIblMaterialBinding(
@@ -5444,14 +5676,16 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5444
5676
  });
5445
5677
  }
5446
5678
  const transmissionSampler = transmissionBackdropView != null ? effectiveSkylightResources.prefilterSampler : pipelineState.defaultSampler;
5679
+ const keepMediumBackdropSlots = surfaceMediumResources !== void 0;
5447
5680
  const smMergedEntries = assembleMaterialWithSkylightEntries(
5448
5681
  smBaseEntries,
5449
5682
  effectiveSkylightResources,
5450
- transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage) ? {
5683
+ transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage) || keepMediumBackdropSlots ? {
5451
5684
  sampler: transmissionSampler,
5452
- ...transmissionBackdropView === void 0 ? {} : { backdropView: transmissionBackdropView }
5685
+ ...transmissionBackdropView === void 0 ? { backdropView: pipelineState.defaultWhiteTextureView } : { backdropView: transmissionBackdropView }
5453
5686
  } : null,
5454
- physicalTextureInjections
5687
+ physicalTextureInjections,
5688
+ surfaceMediumResources
5455
5689
  );
5456
5690
  if (runtime.device.caps.storageBuffer) {
5457
5691
  smMergedEntries.push({
@@ -5480,6 +5714,14 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5480
5714
  entityKey,
5481
5715
  materialHandle: smMaterialHandle,
5482
5716
  shader: smShaderId,
5717
+ surfaceModel: submeshMaterial.surfaceModel,
5718
+ layoutIdentity: getOpaqueResourceIdentity(smMaterialBgl),
5719
+ bindings: smMergedEntries.map((entry) => entry.binding),
5720
+ graphResources: {
5721
+ rawDepth: surfaceRawDepthView != null,
5722
+ nearestLayer: surfaceNearestLayerView != null,
5723
+ nearestDepth: surfaceNearestDepthView != null
5724
+ },
5483
5725
  paramSnapshot: submeshMaterial.paramSnapshot,
5484
5726
  handleTypes: materialCacheHandles.map((handle) => typeof handle)
5485
5727
  })}`
@@ -5595,6 +5837,111 @@ function prepareMaterialSkylight(c) {
5595
5837
  );
5596
5838
  }
5597
5839
 
5840
+ // src/record/probe-blend-buffer.ts
5841
+ function isProbeBlendProjection(input) {
5842
+ return !Array.isArray(input);
5843
+ }
5844
+ function retireProbeBlendRecordBuffer(buffer) {
5845
+ const destroy = () => {
5846
+ if (!buffer.isDestroyed) void buffer.destroy();
5847
+ };
5848
+ void buffer.device.queue.onSubmittedWorkDone().then(destroy, destroy);
5849
+ }
5850
+ function createCompleteProbeBlendBuffer(device, requiredCapacity, records) {
5851
+ const created = device.createBuffer({
5852
+ label: "probe-blend-records",
5853
+ size: requiredCapacity * PROBE_BLEND_RECORD_STRIDE,
5854
+ usage: (device.caps.storageBuffer ? GPU_BUFFER_USAGE_STORAGE : GPU_BUFFER_USAGE_UNIFORM) | GPU_BUFFER_USAGE_COPY_DST,
5855
+ mappedAtCreation: false
5856
+ });
5857
+ if (!created.ok) throw created.error;
5858
+ const candidate = new GpuBuffer(device, created.value);
5859
+ const cache3 = /* @__PURE__ */ new Map();
5860
+ try {
5861
+ for (const { cacheKey, record } of records) {
5862
+ const uploaded = device.queue.writeBuffer(
5863
+ candidate.handle,
5864
+ probeBlendRecordOffset(record.objectKey),
5865
+ record.bytes
5866
+ );
5867
+ if (!uploaded.ok) throw uploaded.error;
5868
+ cache3.set(cacheKey, {
5869
+ generation: record.generation,
5870
+ bytes: new Uint8Array(record.bytes)
5871
+ });
5872
+ }
5873
+ } catch (cause) {
5874
+ void candidate.destroy();
5875
+ throw cause;
5876
+ }
5877
+ return { buffer: candidate, cache: cache3 };
5878
+ }
5879
+ function ensureProbeBlendRecordBuffer(device, frameState, input) {
5880
+ const projection = input !== void 0 && isProbeBlendProjection(input) ? input : void 0;
5881
+ const records = input === void 0 ? [] : projection?.records ?? input;
5882
+ let buffer = frameState.probeBlendRecordBuffer;
5883
+ const accepted = frameState.probeBlendRecordProjection;
5884
+ if (projection !== void 0 && accepted?.projection === projection && accepted.device === device) {
5885
+ if (records.length === 0) return void 0;
5886
+ if (accepted.buffer === buffer && buffer !== void 0 && !buffer.isDestroyed) {
5887
+ return buffer.handle;
5888
+ }
5889
+ }
5890
+ if (records.length === 0) {
5891
+ if (projection !== void 0) {
5892
+ frameState.probeBlendBuffers.clear();
5893
+ frameState.probeBlendRecordProjection = {
5894
+ projection,
5895
+ device,
5896
+ buffer: void 0
5897
+ };
5898
+ }
5899
+ return void 0;
5900
+ }
5901
+ const requiredCapacity = projection?.capacity ?? records.reduce((capacity, { record }) => Math.max(capacity, record.objectKey + 2), 1);
5902
+ const grows = buffer === void 0 || buffer.isDestroyed || buffer.device !== device || frameState.probeBlendRecordBufferCapacity < requiredCapacity;
5903
+ const hasAcceptedBaseline = projection !== void 0 && accepted !== void 0 && accepted.device === device && accepted.buffer === buffer && buffer !== void 0 && !buffer.isDestroyed && accepted.projection.sourceIdentity === projection.sourceIdentity && accepted.projection.revision === projection.baseRevision;
5904
+ const requiresCompletePublish = grows || projection !== void 0 && (!hasAcceptedBaseline || projection.dirtyRecords.length > 1);
5905
+ if (requiresCompletePublish) {
5906
+ const candidate = createCompleteProbeBlendBuffer(device, requiredCapacity, records);
5907
+ const previous = buffer;
5908
+ buffer = candidate.buffer;
5909
+ frameState.probeBlendRecordBuffer = candidate.buffer;
5910
+ frameState.probeBlendRecordBufferCapacity = requiredCapacity;
5911
+ frameState.probeBlendBuffers.clear();
5912
+ for (const [key, value] of candidate.cache) frameState.probeBlendBuffers.set(key, value);
5913
+ if (projection === void 0) delete frameState.probeBlendRecordProjection;
5914
+ else frameState.probeBlendRecordProjection = { projection, device, buffer: candidate.buffer };
5915
+ if (previous !== void 0) retireProbeBlendRecordBuffer(previous);
5916
+ return candidate.buffer.handle;
5917
+ }
5918
+ if (buffer === void 0) return void 0;
5919
+ const changed = projection?.dirtyRecords ?? records;
5920
+ const cacheUpdates = [];
5921
+ for (const { cacheKey, record } of changed) {
5922
+ const cached = frameState.probeBlendBuffers.get(cacheKey);
5923
+ const unchanged = cached !== void 0 && cached.generation === record.generation && cached.bytes.length === record.bytes.length && cached.bytes.every((value, index) => value === record.bytes[index]);
5924
+ if (unchanged) continue;
5925
+ const uploaded = device.queue.writeBuffer(
5926
+ buffer.handle,
5927
+ probeBlendRecordOffset(record.objectKey),
5928
+ record.bytes
5929
+ );
5930
+ if (!uploaded.ok) throw uploaded.error;
5931
+ cacheUpdates.push([
5932
+ cacheKey,
5933
+ { generation: record.generation, bytes: new Uint8Array(record.bytes) }
5934
+ ]);
5935
+ }
5936
+ for (const [cacheKey, value] of cacheUpdates) frameState.probeBlendBuffers.set(cacheKey, value);
5937
+ for (const cacheKey of projection?.removedCacheKeys ?? []) {
5938
+ frameState.probeBlendBuffers.delete(cacheKey);
5939
+ }
5940
+ if (projection === void 0) delete frameState.probeBlendRecordProjection;
5941
+ else frameState.probeBlendRecordProjection = { projection, device, buffer };
5942
+ return buffer.handle;
5943
+ }
5944
+
5598
5945
  // src/record/main-pass-geometry.ts
5599
5946
  function sameOpaqueTemporalDraw(a, b) {
5600
5947
  return (isStandardPbrMaterialShader(a.materialShaderId) || a.tags.SurfaceKind === "standard" && b.tags.SurfaceKind === "standard" && a.tags.SurfaceModule === b.tags.SurfaceModule) && a.materialShaderId === b.materialShaderId && a.renderState?.blend === void 0 && b.renderState?.blend === void 0 && a.renderState?.stencil === void 0 && b.renderState?.stencil === void 0 && a.stencilReference === b.stencilReference && renderStateHash(a.renderState) === renderStateHash(b.renderState);
@@ -5646,9 +5993,10 @@ function isGpuDrivenMainClaimedSubmesh(c, source, submeshIndex, drawIndices) {
5646
5993
  if (drawItemIndex === void 0 || draw === void 0) return false;
5647
5994
  const material = source.materials[draw.materialSlot] ?? source.material;
5648
5995
  const sourceDrawItemIndex = gpuDrivenSourceDrawItemIndex(draw, drawItemIndex);
5996
+ const stableWorld = c.gpuDrivenWorldKeys?.[source.worldId] ?? source.worldId;
5649
5997
  return c.gpuDrivenDrawKeys?.has(
5650
5998
  gpuDrivenDrawKey(
5651
- worldEntityKey(source.worldId, source.entityKey),
5999
+ worldEntityKey(stableWorld, source.entityKey),
5652
6000
  material.materialHandle ?? -1,
5653
6001
  sourceDrawItemIndex
5654
6002
  )
@@ -5734,6 +6082,9 @@ function geometryRenderStateForPass(base, passKind, coverageOnly = false) {
5734
6082
  depthCompare: "less-equal"
5735
6083
  };
5736
6084
  }
6085
+ function authoredTransparentDepthWrite(transparent, renderState) {
6086
+ return (transparent === true || renderState?.blend !== void 0) && renderState?.depthWriteEnabled === true;
6087
+ }
5737
6088
  function geometryRecordPhase(passKind, segment) {
5738
6089
  const pass = passKind === "deferred" ? "g-buffer" : "forward";
5739
6090
  return `record/graph-execute/${pass}/${segment}`;
@@ -5748,13 +6099,16 @@ function submitSubmeshDraws(pass, state, pipeline, instanceDraws, indexed, index
5748
6099
  state.pipeline = pipeline;
5749
6100
  }
5750
6101
  for (const instanceDraw of instanceDraws) {
5751
- if (instanceDraw.instanceBuffer !== state.instancesBuffer || instanceDraw.probeOffset !== state.probeOffset) {
5752
- if (instanceDraw.probeOffset < 0) {
6102
+ if (instanceDraw.instanceBuffer !== state.instancesBuffer || instanceDraw.instanceBindGroup !== state.instanceBindGroup || instanceDraw.probeOffset !== state.probeOffset) {
6103
+ if (instanceDraw.dynamicOffsets !== void 0) {
6104
+ pass.setBindGroup(3, instanceDraw.instanceBindGroup, instanceDraw.dynamicOffsets);
6105
+ } else if (instanceDraw.probeOffset < 0) {
5753
6106
  pass.setBindGroup(3, instanceDraw.instanceBindGroup);
5754
6107
  } else {
5755
6108
  pass.setBindGroup(3, instanceDraw.instanceBindGroup, [instanceDraw.probeOffset]);
5756
6109
  }
5757
6110
  state.instancesBuffer = instanceDraw.instanceBuffer;
6111
+ state.instanceBindGroup = instanceDraw.instanceBindGroup;
5758
6112
  state.probeOffset = instanceDraw.probeOffset;
5759
6113
  }
5760
6114
  if (indexed) {
@@ -5762,7 +6116,7 @@ function submitSubmeshDraws(pass, state, pipeline, instanceDraws, indexed, index
5762
6116
  } else {
5763
6117
  pass.draw(vertexCount, instanceDraw.instanceCount, 0, 0);
5764
6118
  }
5765
- onDraw?.();
6119
+ onDraw?.(instanceDraw, indexed ? "draw-indexed" : "draw");
5766
6120
  }
5767
6121
  }
5768
6122
  function recordPointsLinesDraw(pass, plan) {
@@ -5773,7 +6127,7 @@ function recordPointsLinesDraw(pass, plan) {
5773
6127
  }
5774
6128
  pass.draw(plan.vertexCount, 1, 0, 0);
5775
6129
  }
5776
- function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sampleCount, meshGroup2, meshBindGroup, resolveMaterialBindGroup, passKind = "forward", selectedDispatch, colorFormats = [], coverageOnly = false) {
6130
+ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sampleCount, meshGroup2, meshBindGroup, resolveMaterialBindGroup, passKind = "forward", selectedDispatch, colorFormats = [], coverageOnly = false, fragmentEntryPoint, surfacePass, transparentDepthWrite = false) {
5777
6131
  const {
5778
6132
  runtime,
5779
6133
  pipelineState,
@@ -5809,6 +6163,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5809
6163
  const bindingState = {
5810
6164
  pipeline: null,
5811
6165
  instancesBuffer: null,
6166
+ instanceBindGroup: null,
5812
6167
  probeOffset: -1
5813
6168
  };
5814
6169
  const identityInstanceBuffer = pipelineState.identityInstanceBuffer;
@@ -5828,7 +6183,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5828
6183
  const recordOcclusionCandidate = (draw) => {
5829
6184
  draw();
5830
6185
  };
5831
- const resolveMaterialPipeline = (materialShaderId, renderState, topology, indexFormat, variantSet, colorFormat, layoutProjection, vertexEntry, fragmentEntry, textureMask) => {
6186
+ const resolveMaterialPipeline = (materialShaderId, renderState, topology, indexFormat, variantSet, colorFormat, layoutProjection, vertexEntry, fragmentEntry, textureMask, layoutKind) => {
5832
6187
  const pipelineVariantSet = withCoverageVariant(variantSet);
5833
6188
  const reflectionFallbackFormats = materialShaderId === "forgeax::default-standard-pbr" && c.reflectionFallbackColorFormat !== void 0 ? passKind === "deferred" ? colorFormats.slice(1) : [c.reflectionFallbackColorFormat] : void 0;
5834
6189
  const renderStateKey = renderStateHash(renderState);
@@ -5836,12 +6191,12 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5836
6191
  const cachedLookups = shaderLookupCache?.get(renderStateKey);
5837
6192
  if (cachedLookups !== void 0) {
5838
6193
  for (const cached of cachedLookups) {
5839
- if (cached.isHdrTarget === isHdrTarget && cached.renderStateKey === renderStateKey && cached.topology === topology && cached.indexFormat === indexFormat && cached.variantSet === pipelineVariantSet && cached.vertexEntry === vertexEntry && cached.fragmentEntry === fragmentEntry && cached.textureMask === textureMask && cached.passKind === passKind && cached.layoutProjection.digest === layoutProjection.digest && cached.sampleCount === sampleCount && cached.colorFormatOverride === colorFormat && cached.additionalColorFormats?.join(",") === reflectionFallbackFormats?.join(",")) {
6194
+ if (cached.isHdrTarget === isHdrTarget && cached.renderStateKey === renderStateKey && cached.topology === topology && cached.indexFormat === indexFormat && cached.variantSet === pipelineVariantSet && cached.vertexEntry === vertexEntry && cached.fragmentEntry === fragmentEntry && cached.textureMask === textureMask && cached.layoutKind === layoutKind && cached.passKind === passKind && cached.layoutProjection.digest === layoutProjection.digest && cached.sampleCount === sampleCount && cached.colorFormatOverride === colorFormat && cached.additionalColorFormats?.join(",") === reflectionFallbackFormats?.join(",")) {
5840
6195
  return cached.handle;
5841
6196
  }
5842
6197
  }
5843
6198
  }
5844
- const resolvedVariantSetResult = runtime.getMaterialArtifact?.(materialShaderId) !== void 0 ? { ok: true, value: void 0 } : pipelineVariantSet === void 0 && (materialShaderId === "forgeax::sprite" || materialShaderId === "forgeax::sprite-lit") ? { ok: true, value: void 0 } : variantSetFromVertexLayoutProjection(layoutProjection, pipelineVariantSet);
6199
+ const resolvedVariantSetResult = runtime.getMaterialArtifact?.(materialShaderId) !== void 0 && layoutKind === void 0 ? { ok: true, value: void 0 } : pipelineVariantSet === void 0 && (materialShaderId === "forgeax::sprite" || materialShaderId === "forgeax::sprite-lit") ? { ok: true, value: void 0 } : variantSetFromVertexLayoutProjection(layoutProjection, pipelineVariantSet);
5845
6200
  if (!resolvedVariantSetResult.ok) {
5846
6201
  runtime.errorRegistry.fire(resolvedVariantSetResult.error);
5847
6202
  return null;
@@ -5864,7 +6219,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5864
6219
  void 0,
5865
6220
  layoutProjection,
5866
6221
  void 0,
5867
- void 0,
6222
+ layoutKind,
5868
6223
  void 0,
5869
6224
  reflectionFallbackFormats,
5870
6225
  vertexEntry,
@@ -5889,6 +6244,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5889
6244
  colorFormatOverride: colorFormat,
5890
6245
  additionalColorFormats: reflectionFallbackFormats,
5891
6246
  textureMask,
6247
+ layoutKind,
5892
6248
  handle
5893
6249
  };
5894
6250
  if (shaderLookupCache === void 0) {
@@ -5907,6 +6263,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5907
6263
  for (let i = 0; i < validatedOrdered.length; i++) {
5908
6264
  const entry = validatedOrdered[i];
5909
6265
  if (entry === void 0) continue;
6266
+ if (c.foldDispatchPlan?.skipIndices.has(i) === true) continue;
5910
6267
  const pointsLinesSubmission = c.pointsLines?.prepare(entry, clusteredLighting);
5911
6268
  if (entry.source.pointsLines !== void 0 && pointsLinesSubmission?.plan.drawCount !== 1)
5912
6269
  continue;
@@ -5989,8 +6346,17 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5989
6346
  }
5990
6347
  }
5991
6348
  dispatchCounts.unlit += 1;
5992
- const instanceDraws = resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, false);
5993
- if (instanceDraws === null) continue;
6349
+ const fold = c.foldDispatchPlan?.headBuckets.get(i);
6350
+ const foldBuffer = fold === void 0 ? null : resolveFoldInstanceBuffer(c, fold, i);
6351
+ const baseInstanceDraws = fold === void 0 ? resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, false) : foldBuffer === null ? null : [
6352
+ {
6353
+ instanceBuffer: foldBuffer,
6354
+ instanceBindGroup: resolveGeometryInstancesBindGroup(c, foldBuffer, void 0),
6355
+ probeOffset: -1,
6356
+ instanceCount: fold.bucketSize
6357
+ }
6358
+ ];
6359
+ if (baseInstanceDraws === null) continue;
5994
6360
  let group2BindGroup = meshGroup2;
5995
6361
  meshGroup2DynamicOffsets[0] = i * MESH_PER_ENTITY_STRIDE;
5996
6362
  let group2DynamicOffsets = meshGroup2DynamicOffsets;
@@ -6133,10 +6499,11 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6133
6499
  if (passKind === "forward" && isGpuDrivenMainClaimedSubmesh(c, entry.source, smIdx, gpuDrivenDrawIndices)) {
6134
6500
  continue;
6135
6501
  }
6136
- const draws = selectedDispatch === void 0 ? [void 0] : materialPasses.get(entry.renderableIndex)?.get(submeshMaterial.materialHandle ?? 0) ?? [];
6502
+ const selectedMaterialPasses = materialPasses.get(entry.renderableIndex)?.get(submeshMaterial.materialHandle ?? 0);
6503
+ const draws = selectedDispatch === void 0 || selectedMaterialPasses === void 0 && submeshMaterial.surfaceModel === "single-layer-medium" && matchedMaterials?.get(entry.renderableIndex)?.has(submeshMaterial.materialHandle ?? 0) ? [void 0] : selectedMaterialPasses ?? [];
6137
6504
  for (const selectedPass of draws) {
6138
6505
  const vertexEntry = passKind === "temporal" ? void 0 : selectedPass?.vertexEntry;
6139
- const fragmentEntry = passKind === "temporal" ? void 0 : selectedPass?.fragmentEntry;
6506
+ const fragmentEntry = passKind === "temporal" ? void 0 : fragmentEntryPoint ?? selectedPass?.fragmentEntry;
6140
6507
  const selectedShaderId = selectedPass === void 0 ? submeshMaterial.materialShaderId : selectedPass.materialShaderId;
6141
6508
  const selectedRenderState = selectedPass === void 0 ? submeshMaterial.renderState : selectedPass.renderState;
6142
6509
  const selectedStencil = (selectedPass === void 0 ? entry.stencilReference : selectedPass.stencilReference) ?? 0;
@@ -6182,7 +6549,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6182
6549
  pass.setBindGroup(1, perSubmeshBg, materialGroup1DynamicOffsets, 0, 1);
6183
6550
  const smTopology = sm.topology;
6184
6551
  const smMaterialShaderId = selectedPass !== void 0 ? selectedShaderId : entry.source.skin !== void 0 ? isStandardPbrSkinMaterialShader(submeshMaterial.materialShaderId) ? submeshMaterial.materialShaderId : SKIN_MATERIAL_SHADER_ID : submeshMaterial.materialShaderId;
6185
- const probeBlendAvailable = probeBlendRecordAvailable && isStandardPbrMaterialShader(smMaterialShaderId);
6552
+ const probeBlendAvailable = probeBlendRecordAvailable && (isStandardPbrMaterialShader(smMaterialShaderId) || submeshMaterial.surfaceModel === "single-layer-medium");
6186
6553
  const isSpriteShader = smMaterialShaderId === "forgeax::sprite" || smMaterialShaderId === "forgeax::sprite-lit";
6187
6554
  const basePipelineRenderState = isSpriteShader ? {
6188
6555
  ...selectedRenderState,
@@ -6191,11 +6558,21 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6191
6558
  cullMode: "none",
6192
6559
  blend: selectedRenderState?.blend ?? SPRITE_PREMULTIPLIED_ALPHA_BLEND
6193
6560
  } : geometryRenderStateForTopology(smTopology, selectedRenderState);
6194
- const pipelineRenderState = geometryRenderStateForPass(
6561
+ let pipelineRenderState = geometryRenderStateForPass(
6195
6562
  basePipelineRenderState,
6196
6563
  passKind,
6197
6564
  coverageOnly
6198
6565
  );
6566
+ if (transparentDepthWrite && passKind === "forward" && (submeshMaterial.transparent === true || selectedRenderState?.blend !== void 0)) {
6567
+ pipelineRenderState = {
6568
+ ...pipelineRenderState,
6569
+ depthWriteEnabled: authoredTransparentDepthWrite(
6570
+ submeshMaterial.transparent,
6571
+ selectedRenderState
6572
+ ),
6573
+ depthCompare: "less-equal"
6574
+ };
6575
+ }
6199
6576
  let smPipelineHandle;
6200
6577
  let materialGroup2Contract;
6201
6578
  let materialPipelineEntry = null;
@@ -6240,7 +6617,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6240
6617
  );
6241
6618
  const transmissionAvailable = requestsStandardTransmissionVariant(submeshMaterial);
6242
6619
  const materialCapabilityVariantSet = transmissionAvailable && !capabilityVariantSet.includes("TRANSMISSION_AVAILABLE=") ? `${capabilityVariantSet}+TRANSMISSION_AVAILABLE=true` : capabilityVariantSet;
6243
- const variantSet = isSpriteShader ? smMaterialShaderId === "forgeax::sprite" && entry.source.spriteInstances !== void 0 ? "" : void 0 : entry.variantSet === void 0 ? materialCapabilityVariantSet : `${materialCapabilityVariantSet}+${entry.variantSet}`;
6620
+ const variantSet = isSpriteShader ? smMaterialShaderId === "forgeax::sprite-lit" ? materialCapabilityVariantSet : entry.source.spriteInstances !== void 0 ? "" : void 0 : entry.variantSet === void 0 ? materialCapabilityVariantSet : `${materialCapabilityVariantSet}+${entry.variantSet}`;
6244
6621
  const cachedPipeline = resolveMaterialPipeline(
6245
6622
  smMaterialShaderId,
6246
6623
  pipelineRenderState,
@@ -6251,7 +6628,8 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6251
6628
  entry.mesh.layoutProjection,
6252
6629
  vertexEntry,
6253
6630
  fragmentEntry,
6254
- submeshMaterial.standardTextureMask
6631
+ submeshMaterial.standardTextureMask,
6632
+ submeshMaterial.surfaceModel === "single-layer-medium" && passKind === "forward" ? capabilityVariantSet.includes("CLUSTER_FORWARD_AVAILABLE=true") ? "surface-direct-cluster-pbr" : "surface-direct-pbr" : void 0
6255
6633
  );
6256
6634
  materialPipelineEntry = cachedPipeline;
6257
6635
  smPipelineHandle = cachedPipeline?.pipeline ?? null;
@@ -6271,13 +6649,18 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6271
6649
  }
6272
6650
  continue;
6273
6651
  }
6274
- const instanceDraws2 = resolveGeometryInstanceBuffer(
6652
+ const resolvedInstanceDraws = probeBlendAvailable ? resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, true) : baseInstanceDraws;
6653
+ if (resolvedInstanceDraws === null) continue;
6654
+ const compactDrawIndex = gpuDrivenDrawIndices.get(smIdx);
6655
+ const compactDraw = compactDrawIndex === void 0 ? void 0 : entry.source.gpuDrivenDraws?.[compactDrawIndex];
6656
+ const sourceDrawItemIndex = compactDrawIndex === void 0 || compactDraw === void 0 ? smIdx : gpuDrivenSourceDrawItemIndex(compactDraw, compactDrawIndex);
6657
+ const instanceDraws = submeshMaterial.surfaceModel === "single-layer-medium" && passKind === "forward" ? resolveSurfaceDirectInstanceDraws(
6275
6658
  c,
6276
6659
  entry,
6277
- identityInstanceDraws,
6278
- probeBlendAvailable
6279
- );
6280
- if (instanceDraws2 === null) continue;
6660
+ sourceDrawItemIndex,
6661
+ resolvedInstanceDraws
6662
+ ) : resolvedInstanceDraws;
6663
+ if (instanceDraws === null) continue;
6281
6664
  if (!isSkinEntry) {
6282
6665
  materialGroup2Contract = materialPipelineEntry?.group2Contract;
6283
6666
  if (materialGroup2Contract === void 0) continue;
@@ -6319,12 +6702,29 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6319
6702
  pass,
6320
6703
  bindingState,
6321
6704
  smPipelineHandle,
6322
- instanceDraws2,
6705
+ instanceDraws,
6323
6706
  entry.mesh.indexed,
6324
6707
  sm.indexCount,
6325
6708
  sm.vertexCount,
6326
6709
  sm.indexOffset,
6327
- () => c.onRenderableDraw?.(entry)
6710
+ (draw, command) => {
6711
+ c.onRenderableDraw?.(entry, smIdx);
6712
+ if (surfacePass === void 0 || draw.surfaceFrameBase === void 0) return;
6713
+ c.frameState.surfaceSubmissionObservation?.record(surfacePass, {
6714
+ kind: command,
6715
+ count: entry.mesh.indexed ? sm.indexCount : sm.vertexCount,
6716
+ first: entry.mesh.indexed ? sm.indexOffset : 0,
6717
+ instanceCount: draw.instanceCount,
6718
+ firstInstance: 0,
6719
+ surfaceFrameBase: draw.surfaceFrameBase,
6720
+ memberIds: draw.surfaceMemberIds ?? [],
6721
+ pipelineIdentity: getOpaqueResourceIdentity(smPipelineHandle),
6722
+ ...materialPipelineEntry?.receipt === void 0 ? {} : {
6723
+ receiptIdentity: materialPipelineEntry.receipt.identity,
6724
+ receiptGeneration: materialPipelineEntry.receipt.generation
6725
+ }
6726
+ });
6727
+ }
6328
6728
  )
6329
6729
  );
6330
6730
  } else {
@@ -6337,12 +6737,29 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6337
6737
  pass,
6338
6738
  bindingState,
6339
6739
  smPipelineHandle,
6340
- instanceDraws2,
6740
+ instanceDraws,
6341
6741
  entry.mesh.indexed,
6342
6742
  sm.indexCount,
6343
6743
  sm.vertexCount,
6344
6744
  sm.indexOffset,
6345
- () => c.onRenderableDraw?.(entry)
6745
+ (draw, command) => {
6746
+ c.onRenderableDraw?.(entry, smIdx);
6747
+ if (surfacePass === void 0 || draw.surfaceFrameBase === void 0) return;
6748
+ c.frameState.surfaceSubmissionObservation?.record(surfacePass, {
6749
+ kind: command,
6750
+ count: entry.mesh.indexed ? sm.indexCount : sm.vertexCount,
6751
+ first: entry.mesh.indexed ? sm.indexOffset : 0,
6752
+ instanceCount: draw.instanceCount,
6753
+ firstInstance: 0,
6754
+ surfaceFrameBase: draw.surfaceFrameBase,
6755
+ memberIds: draw.surfaceMemberIds ?? [],
6756
+ pipelineIdentity: getOpaqueResourceIdentity(smPipelineHandle),
6757
+ ...materialPipelineEntry?.receipt === void 0 ? {} : {
6758
+ receiptIdentity: materialPipelineEntry.receipt.identity,
6759
+ receiptGeneration: materialPipelineEntry.receipt.generation
6760
+ }
6761
+ });
6762
+ }
6346
6763
  )
6347
6764
  )
6348
6765
  );
@@ -6354,7 +6771,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6354
6771
  }
6355
6772
  }
6356
6773
  }
6357
- function uploadInstanceRanges(c, inst, buffer, ranges, storageBacked, sourceOffsetInstances = 0) {
6774
+ function uploadInstanceRanges(c, inst, buffer, ranges, storageBacked, sourceOffsetInstances = 0, previousInst = void 0) {
6358
6775
  const strideBytes = (storageBacked ? INSTANCE_STORAGE_STRIDE_FLOATS : 16) * Float32Array.BYTES_PER_ELEMENT;
6359
6776
  const uploadedRanges = [];
6360
6777
  let uploadedBytes = 0;
@@ -6366,7 +6783,20 @@ function uploadInstanceRanges(c, inst, buffer, ranges, storageBacked, sourceOffs
6366
6783
  (sourceOffsetInstances + start) * 16,
6367
6784
  (sourceOffsetInstances + end) * 16
6368
6785
  );
6369
- const payload = storageBacked ? packInstanceStorageBuffer(source) : source;
6786
+ const hasIdentityProof = inst.generations !== void 0 && previousInst?.generations !== void 0;
6787
+ const previousSource = hasIdentityProof ? previousInst?.transforms : previousInst?.transforms.subarray(
6788
+ (sourceOffsetInstances + start) * 16,
6789
+ (sourceOffsetInstances + end) * 16
6790
+ );
6791
+ const currentGenerations = inst.generations?.subarray(
6792
+ sourceOffsetInstances + start,
6793
+ sourceOffsetInstances + end
6794
+ );
6795
+ const previousGenerations = hasIdentityProof ? previousInst?.generations : previousInst?.generations?.subarray(
6796
+ sourceOffsetInstances + start,
6797
+ sourceOffsetInstances + end
6798
+ );
6799
+ const payload = storageBacked ? packInstanceStorageBuffer(source, previousSource, currentGenerations, previousGenerations) : source;
6370
6800
  const written = c.runtime.device.queue.writeBuffer(buffer, start * strideBytes, payload);
6371
6801
  if (!written.ok) {
6372
6802
  c.runtime.errorRegistry.fire(written.error);
@@ -6504,7 +6934,8 @@ function resolveStorageInstanceChunks(c, entry, inst, cap, probeBuffer, probeOff
6504
6934
  active.buffer.handle,
6505
6935
  rangesToUpload,
6506
6936
  true,
6507
- start
6937
+ start,
6938
+ entry.source.temporal?.previousInstances
6508
6939
  );
6509
6940
  for (const range of upload.ranges) {
6510
6941
  uploadedRanges.push({ start: range.start + start, end: range.end + start });
@@ -6540,8 +6971,10 @@ function resolveStorageInstanceChunks(c, entry, inst, cap, probeBuffer, probeOff
6540
6971
  activeBuffer.buffer.handle,
6541
6972
  probeBuffer
6542
6973
  ),
6974
+ ...probeBuffer === void 0 ? {} : { probeBuffer },
6543
6975
  probeOffset,
6544
- instanceCount: count
6976
+ instanceCount: count,
6977
+ firstInstanceOrdinal: start
6545
6978
  });
6546
6979
  }
6547
6980
  if (chunks !== void 0) {
@@ -6583,6 +7016,7 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6583
7016
  pipelineState.identityInstanceBuffer,
6584
7017
  probeBinding?.buffer
6585
7018
  ),
7019
+ ...probeBinding?.buffer === void 0 ? {} : { probeBuffer: probeBinding.buffer },
6586
7020
  probeOffset: probeBinding?.offset ?? -1
6587
7021
  }
6588
7022
  ];
@@ -6661,7 +7095,8 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6661
7095
  active.buffer.handle,
6662
7096
  rangesToUpload,
6663
7097
  false,
6664
- start
7098
+ start,
7099
+ entry.source.temporal?.previousInstances
6665
7100
  );
6666
7101
  for (const range of upload.ranges) {
6667
7102
  uploadedRanges.push({ start: range.start + start, end: range.end + start });
@@ -6694,8 +7129,10 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6694
7129
  active.buffer.handle,
6695
7130
  probeBinding?.buffer
6696
7131
  ),
7132
+ ...probeBinding?.buffer === void 0 ? {} : { probeBuffer: probeBinding.buffer },
6697
7133
  probeOffset: probeBinding?.offset ?? -1,
6698
- instanceCount: count
7134
+ instanceCount: count,
7135
+ firstInstanceOrdinal: start
6699
7136
  });
6700
7137
  }
6701
7138
  if (chunks !== void 0) {
@@ -6749,6 +7186,7 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6749
7186
  if (!bufRes.ok) {
6750
7187
  runtime.errorRegistry.fire(bufRes.error);
6751
7188
  reportInstanceFailure(c, inst, bufRes.error, requestedBytes, cap);
7189
+ return null;
6752
7190
  } else {
6753
7191
  if (cached !== void 0 && !cached.buffer.isDestroyed) {
6754
7192
  const r = cached.buffer.destroy();
@@ -6781,7 +7219,9 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6781
7219
  inst,
6782
7220
  active.buffer.handle,
6783
7221
  ranges,
6784
- !uniformFallback
7222
+ !uniformFallback,
7223
+ 0,
7224
+ entry.source.temporal?.previousInstances
6785
7225
  );
6786
7226
  uploadRanges = upload.ranges;
6787
7227
  uploadedBytes = upload.bytes;
@@ -6823,43 +7263,61 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6823
7263
  {
6824
7264
  instanceBuffer,
6825
7265
  instanceBindGroup: resolveGeometryInstancesBindGroup(c, instanceBuffer, probeBinding?.buffer),
7266
+ ...probeBinding?.buffer === void 0 ? {} : { probeBuffer: probeBinding.buffer },
6826
7267
  probeOffset: probeBinding?.offset ?? -1,
6827
7268
  instanceCount
6828
7269
  }
6829
7270
  ];
6830
7271
  }
7272
+ function resolveSurfaceDirectInstanceDraws(c, entry, drawItemIndex, draws) {
7273
+ const resolve = c.gpuDrivenStandardPbrFrameResources?.surfaceDirectInstances;
7274
+ if (resolve === void 0) {
7275
+ c.runtime.errorRegistry.fire(
7276
+ new RhiError({
7277
+ code: "rhi-not-available",
7278
+ expected: "the prepared Surface producer publishes the direct slot-3 resource closure",
7279
+ hint: "prepare the retained Surface frame before recording direct medium draws"
7280
+ })
7281
+ );
7282
+ return null;
7283
+ }
7284
+ const resolved = [];
7285
+ for (const draw of draws) {
7286
+ const direct = resolve({
7287
+ worldId: entry.source.worldId,
7288
+ entityKey: entry.source.entityKey,
7289
+ drawItemIndex,
7290
+ instanceCount: draw.instanceCount,
7291
+ firstInstanceOrdinal: draw.firstInstanceOrdinal ?? 0,
7292
+ instanceBuffer: draw.instanceBuffer,
7293
+ ...draw.probeBuffer === void 0 ? {} : { probeBuffer: draw.probeBuffer },
7294
+ ...draw.probeOffset < 0 ? {} : {
7295
+ probeOffset: draw.probeOffset
7296
+ }
7297
+ });
7298
+ if (!direct.ok) {
7299
+ c.runtime.errorRegistry.fire(direct.error);
7300
+ return null;
7301
+ }
7302
+ resolved.push({
7303
+ ...draw,
7304
+ instanceBindGroup: direct.value.bindGroup,
7305
+ dynamicOffsets: direct.value.dynamicOffsets,
7306
+ surfaceFrameBase: direct.value.frameBase,
7307
+ surfaceMemberIds: direct.value.memberIds
7308
+ });
7309
+ }
7310
+ return resolved;
7311
+ }
6831
7312
  function resolveProbeBlendBuffer(c, record, entityKey) {
6832
7313
  const { runtime, frameState } = c;
6833
- const usage = runtime.device.caps.storageBuffer ? GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST : GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
6834
7314
  if (record === void 0) throw new Error("probe blend record is required for probe allocation");
6835
7315
  if (entityKey === void 0) throw new Error("probe blend record requires an entity key");
6836
- const offset = probeBlendRecordOffset(record.objectKey);
6837
- const requiredCapacity = record.objectKey + 2;
6838
- let buffer = frameState.probeBlendRecordBuffer;
6839
- if (buffer === void 0 || frameState.probeBlendRecordBufferCapacity < requiredCapacity) {
6840
- const created = runtime.device.createBuffer({
6841
- label: "probe-blend-records",
6842
- size: requiredCapacity * PROBE_BLEND_RECORD_STRIDE,
6843
- usage,
6844
- mappedAtCreation: false
6845
- });
6846
- if (!created.ok) throw created.error;
6847
- buffer = new GpuBuffer(runtime.device, created.value);
6848
- frameState.probeBlendRecordBuffer = buffer;
6849
- frameState.probeBlendRecordBufferCapacity = requiredCapacity;
6850
- frameState.probeBlendBuffers.clear();
6851
- }
6852
- const cached = frameState.probeBlendBuffers.get(entityKey);
6853
- const unchanged = cached !== void 0 && cached.generation === record.generation && cached.bytes.length === record.bytes.length && cached.bytes.every((value, index) => value === record.bytes[index]);
6854
- if (!unchanged) {
6855
- const uploaded = runtime.device.queue.writeBuffer(buffer.handle, offset, record.bytes);
6856
- if (!uploaded.ok) throw uploaded.error;
6857
- frameState.probeBlendBuffers.set(entityKey, {
6858
- generation: record.generation,
6859
- bytes: new Uint8Array(record.bytes)
6860
- });
6861
- }
6862
- return { buffer: buffer.handle, offset };
7316
+ const buffer = ensureProbeBlendRecordBuffer(runtime.device, frameState, [
7317
+ { cacheKey: entityKey, record }
7318
+ ]);
7319
+ if (buffer === void 0) throw new Error("probe blend record buffer allocation failed");
7320
+ return { buffer, offset: probeBlendRecordOffset(record.objectKey) };
6863
7321
  }
6864
7322
  function resolveGeometryInstancesBindGroup(c, instanceBuffer, probeBuffer) {
6865
7323
  const { runtime, pipelineState, frameState, bindGroupCounts } = c;
@@ -7182,50 +7640,10 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, resolveMaterialB
7182
7640
  const spriteInst = spriteEntry.source.instances;
7183
7641
  const useFold = foldHeadBucket !== void 0 && spriteInst === void 0;
7184
7642
  if (useFold && foldHeadBucket !== void 0) {
7185
- const bucketCacheKey = -1 - ((foldHeadBucket.materialHandle & 65535) << 16 | i & 65535);
7186
- const uniformFallback = runtime.device.caps.storageBuffer === false;
7187
- const bucketPayload = uniformFallback ? foldHeadBucket.transforms : packInstanceStorageBuffer(foldHeadBucket.transforms);
7188
- const bucketBytes = bucketPayload.byteLength;
7189
- const bucketBufUsage = uniformFallback ? GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST : GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
7190
- const cachedBucket = frameState.instanceBuffers.get(bucketCacheKey);
7191
- let activeBucket = null;
7192
- if (cachedBucket !== void 0 && cachedBucket.uploadedArchVersion === foldHeadBucket.bucketSize && cachedBucket.uploadedByteLength === bucketBytes) {
7193
- activeBucket = cachedBucket;
7194
- } else if (bucketBytes > 0) {
7195
- const bufRes = runtime.device.createBuffer({
7196
- size: bucketBytes,
7197
- usage: bucketBufUsage,
7198
- mappedAtCreation: false
7199
- });
7200
- if (!bufRes.ok) {
7201
- runtime.errorRegistry.fire(bufRes.error);
7202
- } else {
7203
- if (cachedBucket !== void 0 && !cachedBucket.buffer.isDestroyed) {
7204
- const r = cachedBucket.buffer.destroy();
7205
- if (!r.ok) runtime.errorRegistry.fire(r.error);
7206
- }
7207
- const newBuf = new GpuBuffer(runtime.device, bufRes.value);
7208
- activeBucket = {
7209
- buffer: newBuf,
7210
- uploadedArchVersion: foldHeadBucket.bucketSize,
7211
- uploadedByteLength: bucketBytes
7212
- };
7213
- frameState.instanceBuffers.set(bucketCacheKey, activeBucket);
7214
- }
7215
- }
7216
- if (activeBucket !== null) {
7217
- const writeRes = runtime.device.queue.writeBuffer(
7218
- activeBucket.buffer.handle,
7219
- 0,
7220
- bucketPayload
7221
- );
7222
- if (!writeRes.ok) {
7223
- runtime.errorRegistry.fire(writeRes.error);
7224
- } else {
7225
- spriteInstanceBuffer = activeBucket.buffer.handle;
7226
- spriteInstanceCount = foldHeadBucket.bucketSize;
7227
- }
7228
- }
7643
+ const buffer = resolveFoldInstanceBuffer(c, foldHeadBucket, i);
7644
+ if (buffer === null) continue;
7645
+ spriteInstanceBuffer = buffer;
7646
+ spriteInstanceCount = foldHeadBucket.bucketSize;
7229
7647
  } else if (spriteInst !== void 0) {
7230
7648
  const uniformFallback = runtime.device.caps.storageBuffer === false;
7231
7649
  let spriteBufUsage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
@@ -7251,13 +7669,18 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, resolveMaterialB
7251
7669
  );
7252
7670
  spritePass.setBindGroup(3, spriteInstBg);
7253
7671
  spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
7254
- c.onRenderableDraw?.(spriteEntry);
7672
+ c.onRenderableDraw?.(spriteEntry, 0);
7255
7673
  continue;
7256
7674
  }
7257
7675
  spriteBufUsage = GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
7258
7676
  }
7259
7677
  {
7260
- const instancePayload = uniformFallback ? spriteInst.transforms : packInstanceStorageBuffer(spriteInst.transforms);
7678
+ const instancePayload = uniformFallback ? spriteInst.transforms : packInstanceStorageBuffer(
7679
+ spriteInst.transforms,
7680
+ spriteEntry.source.temporal?.previousInstances?.transforms,
7681
+ spriteInst.generations,
7682
+ spriteEntry.source.temporal?.previousInstances?.generations
7683
+ );
7261
7684
  const requestedBytes = instancePayload.byteLength;
7262
7685
  const cap = runtime.device.limits.maxStorageBufferBindingSize;
7263
7686
  if (typeof cap === "number" && requestedBytes > cap) {
@@ -7341,7 +7764,7 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, resolveMaterialB
7341
7764
  spritePass.setBindGroup(1, spritePassBg, [materialSlot * MATERIAL_PER_ENTITY_STRIDE]);
7342
7765
  spritePass.setBindGroup(3, spriteInstancesBg);
7343
7766
  spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
7344
- c.onRenderableDraw?.(spriteEntry);
7767
+ c.onRenderableDraw?.(spriteEntry, 0);
7345
7768
  }
7346
7769
  }
7347
7770
  function resolveSpriteInstancesBuffer(c, spriteEntry, fallbackBuffer, fallbackCount) {
@@ -7626,6 +8049,29 @@ function selectLod(input) {
7626
8049
 
7627
8050
  // src/gpu-driven/batch-topology.ts
7628
8051
  var GPU_DRIVEN_SKIN_FLAG = 2147483648;
8052
+ function inspectResourceClassSplits(plan) {
8053
+ const groups = /* @__PURE__ */ new Map();
8054
+ for (const batch of plan.batches) {
8055
+ const resourceIdentity = batch.key.resourceIdentity ?? batch.key.materialResourceClass;
8056
+ const group = groups.get(resourceIdentity) ?? { batchIds: [], candidateCount: 0 };
8057
+ group.batchIds.push(batch.batchId);
8058
+ group.candidateCount += batch.candidates.length;
8059
+ groups.set(resourceIdentity, group);
8060
+ }
8061
+ const resourceClassSplits = [...groups.entries()].sort(([left], [right]) => left.localeCompare(right)).map(
8062
+ ([resourceIdentity, group]) => Object.freeze({
8063
+ resourceIdentity,
8064
+ batchIds: Object.freeze([...group.batchIds].sort((left, right) => left - right)),
8065
+ candidateCount: group.candidateCount
8066
+ })
8067
+ );
8068
+ const resourceClassSplitReasons = resourceClassSplits.length <= 1 ? [] : resourceClassSplits.map(({ resourceIdentity }) => `resource-class:${resourceIdentity}`);
8069
+ return Object.freeze({
8070
+ resourceClassCount: resourceClassSplits.length,
8071
+ resourceClassSplits: Object.freeze(resourceClassSplits),
8072
+ resourceClassSplitReasons: Object.freeze(resourceClassSplitReasons)
8073
+ });
8074
+ }
7629
8075
  var submissionCandidateMembershipCache = /* @__PURE__ */ new WeakMap();
7630
8076
  function buildSubmissionCandidateMembership(source) {
7631
8077
  const cached = submissionCandidateMembershipCache.get(source);
@@ -7724,7 +8170,8 @@ function eligibleDraws(slot) {
7724
8170
  materialResourceClass: draw.materialResourceClass,
7725
8171
  preparedIdentity,
7726
8172
  resourceIdentity: draw.materialResourceClass,
7727
- admission
8173
+ admission,
8174
+ materialPass: material.deferredPass === true ? "deferred" : "forward-only"
7728
8175
  },
7729
8176
  prepared,
7730
8177
  ...candidatePayload(draw, snapshot)
@@ -7992,6 +8439,7 @@ var BatchTopology = class {
7992
8439
  inspect() {
7993
8440
  let candidateCount = 0;
7994
8441
  for (const batch of this.batches.values()) candidateCount += batch.candidates.size;
8442
+ const resourceClasses = inspectResourceClassSplits(this.plan());
7995
8443
  return {
7996
8444
  revision: this.revision,
7997
8445
  batchCount: this.batches.size,
@@ -8003,7 +8451,10 @@ var BatchTopology = class {
8003
8451
  membershipChecks: this.membershipChecks,
8004
8452
  membershipAllocations: this.membershipAllocations,
8005
8453
  candidateAdds: this.candidateAdds,
8006
- candidateRemoves: this.candidateRemoves
8454
+ candidateRemoves: this.candidateRemoves,
8455
+ resourceClassCount: resourceClasses.resourceClassCount,
8456
+ resourceClassSplits: resourceClasses.resourceClassSplits,
8457
+ resourceClassSplitReasons: resourceClasses.resourceClassSplitReasons
8007
8458
  };
8008
8459
  }
8009
8460
  add(slot) {
@@ -8089,6 +8540,410 @@ var BatchTopology = class {
8089
8540
  };
8090
8541
  }
8091
8542
  };
8543
+ function decodeSurfaceIndirectParameters(input) {
8544
+ const ranges = input.recording.passes.flatMap(
8545
+ (pass) => pass.ranges.map((range) => ({ pass: pass.pass, ...range }))
8546
+ );
8547
+ if (input.byteOffset < 0 || input.byteLength < 0 || input.byteOffset + input.byteLength > input.bytes.byteLength) {
8548
+ return err$1({
8549
+ code: "indirect-readback-truncated",
8550
+ expected: "the indirect readback range is contained by the mapped buffer",
8551
+ hint: "retain the complete GPU indirect command copy before mapping it",
8552
+ actual: {
8553
+ byteOffset: input.byteOffset,
8554
+ byteLength: input.byteLength,
8555
+ bufferBytes: input.bytes.byteLength
8556
+ }
8557
+ });
8558
+ }
8559
+ const values = new DataView(input.bytes, input.byteOffset, input.byteLength);
8560
+ const decoded = [];
8561
+ for (const range of ranges) {
8562
+ if (range.indirectBufferIdentity !== input.indirectBufferIdentity) {
8563
+ return err$1({
8564
+ code: "indirect-readback-metadata-mismatch",
8565
+ expected: "every Surface indirect range names the copied indirect buffer",
8566
+ hint: "discard the readback and wait for the matching resource generation",
8567
+ actual: {
8568
+ pass: range.pass,
8569
+ expectedBufferIdentity: input.indirectBufferIdentity,
8570
+ actualBufferIdentity: range.indirectBufferIdentity
8571
+ }
8572
+ });
8573
+ }
8574
+ const offset = range.indirectOffset;
8575
+ if (!Number.isInteger(offset) || offset < 0 || offset % 4 !== 0 || offset + 20 > values.byteLength) {
8576
+ return err$1({
8577
+ code: "indirect-readback-truncated",
8578
+ expected: "each indirect range is a 20-byte aligned command inside the copied buffer",
8579
+ hint: "discard truncated selector readback instead of publishing partial draw parameters",
8580
+ actual: { pass: range.pass, indirectOffset: offset, readbackBytes: values.byteLength }
8581
+ });
8582
+ }
8583
+ const indexed = range.kind === "draw-indexed-indirect";
8584
+ decoded.push(
8585
+ Object.freeze({
8586
+ sequence: input.recording.sequence,
8587
+ frameId: input.recording.frameId,
8588
+ deviceGeneration: input.recording.deviceGeneration,
8589
+ resourceGeneration: input.recording.resourceGeneration,
8590
+ viewIdentity: input.recording.viewIdentity,
8591
+ pass: range.pass,
8592
+ kind: range.kind,
8593
+ indirectBufferIdentity: range.indirectBufferIdentity,
8594
+ indirectOffset: offset,
8595
+ count: values.getUint32(offset, true),
8596
+ first: values.getUint32(offset + 8, true),
8597
+ instanceCount: values.getUint32(offset + 4, true),
8598
+ baseVertex: indexed ? values.getInt32(offset + 12, true) : 0,
8599
+ firstInstance: values.getUint32(indexed ? offset + 16 : offset + 12, true)
8600
+ })
8601
+ );
8602
+ }
8603
+ return ok(Object.freeze(decoded));
8604
+ }
8605
+ var MAX_COMMANDS_PER_PASS = 32;
8606
+ function isIndirect(command) {
8607
+ return command.kind === "draw-indirect" || command.kind === "draw-indexed-indirect";
8608
+ }
8609
+ function sameReadbackPass(receipt, snapshot) {
8610
+ if (receipt.pass !== snapshot.pass || receipt.totalCommandCount !== snapshot.totalCommandCount || receipt.savedCommandCount !== snapshot.savedCommandCount || receipt.droppedCommandCount !== snapshot.droppedCommandCount || receipt.truncated !== snapshot.truncated) {
8611
+ return false;
8612
+ }
8613
+ const ranges = receipt.commands.flatMap(
8614
+ (command) => command.kind === "draw-indirect" || command.kind === "draw-indexed-indirect" ? [
8615
+ {
8616
+ kind: command.kind,
8617
+ indirectBufferIdentity: command.indirectBufferIdentity,
8618
+ indirectOffset: command.indirectOffset
8619
+ }
8620
+ ] : []
8621
+ );
8622
+ return ranges.length === snapshot.ranges.length && ranges.every((range, index) => {
8623
+ const expected = snapshot.ranges[index];
8624
+ return expected !== void 0 && range.kind === expected.kind && range.indirectBufferIdentity === expected.indirectBufferIdentity && range.indirectOffset === expected.indirectOffset;
8625
+ });
8626
+ }
8627
+ function sameIndirectParameters(recording, parameters) {
8628
+ const expected = recording.passes.flatMap(
8629
+ (pass) => pass.ranges.map((range) => ({ pass: pass.pass, ...range }))
8630
+ );
8631
+ return expected.length === parameters.length && expected.every((range, index) => {
8632
+ const actual = parameters[index];
8633
+ return actual !== void 0 && actual.sequence === recording.sequence && actual.frameId === recording.frameId && actual.deviceGeneration === recording.deviceGeneration && actual.resourceGeneration === recording.resourceGeneration && actual.viewIdentity === recording.viewIdentity && actual.pass === range.pass && actual.kind === range.kind && actual.indirectBufferIdentity === range.indirectBufferIdentity && actual.indirectOffset === range.indirectOffset;
8634
+ });
8635
+ }
8636
+ var SurfaceSubmissionCandidate = class {
8637
+ constructor(owner, sequence, frameId, requestedLane, deviceGeneration, viewIdentity, resourceGeneration) {
8638
+ this.owner = owner;
8639
+ this.sequence = sequence;
8640
+ this.frameId = frameId;
8641
+ this.requestedLane = requestedLane;
8642
+ this.deviceGeneration = deviceGeneration;
8643
+ this.viewIdentity = viewIdentity;
8644
+ this.resolvedResourceGeneration = resourceGeneration;
8645
+ }
8646
+ owner;
8647
+ sequence;
8648
+ frameId;
8649
+ requestedLane;
8650
+ deviceGeneration;
8651
+ viewIdentity;
8652
+ passes = /* @__PURE__ */ new Map();
8653
+ state = "recording";
8654
+ resolvedResourceGeneration;
8655
+ actualLaneReason;
8656
+ setResourceGeneration(generation) {
8657
+ if (this.state === "recording") this.resolvedResourceGeneration = generation;
8658
+ }
8659
+ get resourceGeneration() {
8660
+ return this.resolvedResourceGeneration;
8661
+ }
8662
+ setActualLaneReason(reason) {
8663
+ if (this.state === "recording") this.actualLaneReason = reason;
8664
+ }
8665
+ record(pass, command) {
8666
+ if (this.state !== "recording") return;
8667
+ let recording = this.passes.get(pass);
8668
+ if (recording === void 0) {
8669
+ recording = { commands: [], totalCommandCount: 0, sawIndirect: false };
8670
+ this.passes.set(pass, recording);
8671
+ }
8672
+ recording.totalCommandCount += 1;
8673
+ recording.sawIndirect ||= isIndirect(command);
8674
+ if (recording.commands.length >= MAX_COMMANDS_PER_PASS) return;
8675
+ const programEvidence = command.receiptIdentity === void 0 || command.receiptGeneration === void 0 ? "missing" : "producer-receipt";
8676
+ recording.commands.push(Object.freeze({ ...command, programEvidence }));
8677
+ }
8678
+ /** Snapshot consumed only by the readback copy encoded for this candidate. */
8679
+ gpuReadbackSnapshot() {
8680
+ if (this.state !== "submitted") return void 0;
8681
+ const passes = ["nearest-layer", "color"].flatMap((pass) => {
8682
+ const recording = this.passes.get(pass);
8683
+ if (recording === void 0) return [];
8684
+ if (!recording.sawIndirect) return [];
8685
+ const ranges = recording.commands.flatMap(
8686
+ (command) => isIndirect(command) ? [
8687
+ Object.freeze({
8688
+ kind: command.kind,
8689
+ indirectBufferIdentity: command.indirectBufferIdentity,
8690
+ indirectOffset: command.indirectOffset
8691
+ })
8692
+ ] : []
8693
+ );
8694
+ const savedCommandCount = recording.commands.length;
8695
+ return [
8696
+ Object.freeze({
8697
+ pass,
8698
+ totalCommandCount: recording.totalCommandCount,
8699
+ savedCommandCount,
8700
+ droppedCommandCount: recording.totalCommandCount - savedCommandCount,
8701
+ truncated: recording.totalCommandCount > savedCommandCount,
8702
+ ranges: Object.freeze(ranges)
8703
+ })
8704
+ ];
8705
+ });
8706
+ return Object.freeze({
8707
+ sequence: this.sequence,
8708
+ frameId: this.frameId,
8709
+ deviceGeneration: this.deviceGeneration,
8710
+ resourceGeneration: this.resourceGeneration,
8711
+ viewIdentity: this.viewIdentity,
8712
+ passes: Object.freeze(passes)
8713
+ });
8714
+ }
8715
+ get laneReason() {
8716
+ return this.actualLaneReason;
8717
+ }
8718
+ submit(completed, graphGeneration) {
8719
+ if (this.state !== "recording") return;
8720
+ this.state = "submitted";
8721
+ this.owner.submit(this, completed, graphGeneration, this.passes);
8722
+ }
8723
+ abort() {
8724
+ if (this.state === "recording") this.state = "aborted";
8725
+ }
8726
+ };
8727
+ var SurfaceSubmissionObservationOwner = class {
8728
+ constructor(currentDeviceGeneration) {
8729
+ this.currentDeviceGeneration = currentDeviceGeneration;
8730
+ }
8731
+ currentDeviceGeneration;
8732
+ sequence = 0;
8733
+ acceptedSequence = 0;
8734
+ latest;
8735
+ begin(input) {
8736
+ this.sequence += 1;
8737
+ return new SurfaceSubmissionCandidate(
8738
+ this,
8739
+ this.sequence,
8740
+ input.frameId,
8741
+ input.requestedLane,
8742
+ input.deviceGeneration,
8743
+ "main:0",
8744
+ input.resourceGeneration
8745
+ );
8746
+ }
8747
+ inspect() {
8748
+ return this.latest;
8749
+ }
8750
+ /** Attach only selector-visible members copied for this exact completed recording. */
8751
+ publishGpuMembers(readback, targetOrLegacyMembers) {
8752
+ const target = targetOrLegacyMembers === void 0 || Array.isArray(targetOrLegacyMembers) ? void 0 : targetOrLegacyMembers;
8753
+ if (typeof readback === "number" || target === void 0) return;
8754
+ const latest = this.latest;
8755
+ const recording = readback.recording;
8756
+ if (latest === void 0 || latest.status !== "completed" || latest.actualLane !== "gpu-driven" || latest.sequence !== recording.sequence || latest.frameId !== recording.frameId || latest.deviceGeneration !== recording.deviceGeneration || latest.resourceGeneration !== recording.resourceGeneration || latest.viewIdentity !== recording.viewIdentity || latest.frameId !== target.frameId || latest.deviceGeneration !== target.deviceGeneration || latest.passes.length !== recording.passes.length || !latest.passes.every((pass, index) => {
8757
+ const snapshot = recording.passes[index];
8758
+ return snapshot !== void 0 && sameReadbackPass(pass, snapshot);
8759
+ })) {
8760
+ return;
8761
+ }
8762
+ if (readback.indirectParameters === void 0 || !sameIndirectParameters(recording, readback.indirectParameters)) {
8763
+ return;
8764
+ }
8765
+ this.latest = Object.freeze({
8766
+ ...latest,
8767
+ passes: Object.freeze(
8768
+ latest.passes.map((pass) => {
8769
+ const passParameters = readback.indirectParameters?.filter(
8770
+ (parameter) => parameter.pass === pass.pass
8771
+ );
8772
+ return Object.freeze({
8773
+ ...pass,
8774
+ memberEvidence: readback.indirectParameters === void 0 ? "indirect-readback-required" : pass.truncated ? "indirect-visible-readback-truncated" : "indirect-visible-readback",
8775
+ memberIds: Object.freeze([...readback.memberIds]),
8776
+ ...pass.truncated || passParameters === void 0 ? {} : { indirectParameters: Object.freeze(passParameters) }
8777
+ });
8778
+ })
8779
+ )
8780
+ });
8781
+ }
8782
+ submit(candidate, completed, graphGeneration, recordings) {
8783
+ const sequence = candidate.sequence;
8784
+ const passes = ["nearest-layer", "color"].flatMap((pass) => {
8785
+ const recording = recordings.get(pass);
8786
+ if (recording === void 0 || recording.totalCommandCount === 0) return [];
8787
+ const savedCommandCount = recording.commands.length;
8788
+ const truncated = recording.totalCommandCount > savedCommandCount;
8789
+ return [
8790
+ Object.freeze({
8791
+ pass,
8792
+ commandCount: recording.totalCommandCount,
8793
+ totalCommandCount: recording.totalCommandCount,
8794
+ savedCommandCount,
8795
+ droppedCommandCount: recording.totalCommandCount - savedCommandCount,
8796
+ truncated,
8797
+ memberEvidence: recording.sawIndirect ? "indirect-readback-required" : truncated ? "direct-command-members-truncated" : "direct-command-members",
8798
+ commands: Object.freeze([...recording.commands])
8799
+ })
8800
+ ];
8801
+ });
8802
+ if (passes.length === 0) return;
8803
+ const actualLane = [...recordings.values()].some((recording) => recording.sawIndirect) ? "gpu-driven" : "direct";
8804
+ const submitted = Object.freeze({
8805
+ sequence,
8806
+ frameId: candidate.frameId,
8807
+ requestedLane: candidate.requestedLane,
8808
+ actualLane,
8809
+ ...candidate.laneReason === void 0 ? {} : { actualLaneReason: candidate.laneReason },
8810
+ deviceGeneration: candidate.deviceGeneration,
8811
+ graphGeneration,
8812
+ viewIdentity: candidate.viewIdentity,
8813
+ resourceGeneration: candidate.resourceGeneration,
8814
+ status: "submitted",
8815
+ passes: Object.freeze(passes)
8816
+ });
8817
+ this.latest = submitted;
8818
+ void completed.then(
8819
+ () => {
8820
+ if (sequence !== this.sequence || sequence < this.acceptedSequence || this.currentDeviceGeneration() !== candidate.deviceGeneration) {
8821
+ return;
8822
+ }
8823
+ this.acceptedSequence = sequence;
8824
+ this.latest = Object.freeze({ ...submitted, status: "completed" });
8825
+ },
8826
+ () => void 0
8827
+ );
8828
+ }
8829
+ };
8830
+
8831
+ // src/gpu-driven/resource-allocation.ts
8832
+ var GpuResourceAllocationLedger = class {
8833
+ nextId = 1;
8834
+ live = /* @__PURE__ */ new Map();
8835
+ pending = /* @__PURE__ */ new Map();
8836
+ liveBytes = 0;
8837
+ pendingBytes = 0;
8838
+ peakBytes = 0;
8839
+ successfulAllocationCount = 0;
8840
+ successfulAllocationBytes = 0;
8841
+ retiredBytes = 0;
8842
+ failedAllocationRollbacks = 0;
8843
+ failedAllocationRollbackBytes = 0;
8844
+ allocate(bytes) {
8845
+ if (!Number.isFinite(bytes) || bytes < 0) {
8846
+ throw new RangeError(`GPU allocation bytes must be finite and non-negative (got ${bytes})`);
8847
+ }
8848
+ const token = { id: this.nextId++, bytes };
8849
+ this.live.set(token.id, token.bytes);
8850
+ this.liveBytes += token.bytes;
8851
+ this.successfulAllocationCount += 1;
8852
+ this.successfulAllocationBytes += token.bytes;
8853
+ this.updatePeak();
8854
+ return token;
8855
+ }
8856
+ retire(token) {
8857
+ const bytes = this.live.get(token.id);
8858
+ if (bytes === void 0) return;
8859
+ this.live.delete(token.id);
8860
+ this.liveBytes -= bytes;
8861
+ this.pending.set(token.id, bytes);
8862
+ this.pendingBytes += bytes;
8863
+ this.updatePeak();
8864
+ }
8865
+ release(token) {
8866
+ const pendingBytes = this.pending.get(token.id);
8867
+ if (pendingBytes !== void 0) {
8868
+ this.pending.delete(token.id);
8869
+ this.pendingBytes -= pendingBytes;
8870
+ this.retiredBytes += pendingBytes;
8871
+ return;
8872
+ }
8873
+ const liveBytes = this.live.get(token.id);
8874
+ if (liveBytes !== void 0) {
8875
+ this.live.delete(token.id);
8876
+ this.liveBytes -= liveBytes;
8877
+ this.retiredBytes += liveBytes;
8878
+ }
8879
+ }
8880
+ rollback(token) {
8881
+ const bytes = this.live.get(token.id);
8882
+ if (bytes === void 0) return;
8883
+ this.live.delete(token.id);
8884
+ this.liveBytes -= bytes;
8885
+ this.failedAllocationRollbacks += 1;
8886
+ this.failedAllocationRollbackBytes += bytes;
8887
+ }
8888
+ inspect() {
8889
+ return {
8890
+ unit: "engine-allocation-bytes",
8891
+ physicalResidency: "unknown",
8892
+ liveBytes: this.liveBytes,
8893
+ pendingRetirementBytes: this.pendingBytes,
8894
+ peakBytes: this.peakBytes,
8895
+ successfulAllocationCount: this.successfulAllocationCount,
8896
+ successfulAllocationBytes: this.successfulAllocationBytes,
8897
+ pendingRetirementCount: this.pending.size,
8898
+ retiredBytes: this.retiredBytes,
8899
+ failedAllocationRollbacks: this.failedAllocationRollbacks,
8900
+ failedAllocationRollbackBytes: this.failedAllocationRollbackBytes
8901
+ };
8902
+ }
8903
+ updatePeak() {
8904
+ this.peakBytes = Math.max(this.peakBytes, this.liveBytes + this.pendingBytes);
8905
+ }
8906
+ };
8907
+ function combineGpuResourceAllocationInspections(inspections) {
8908
+ if (inspections.length === 0) return void 0;
8909
+ const liveBytes = inspections.reduce((sum, value) => sum + value.liveBytes, 0);
8910
+ const pendingRetirementBytes = inspections.reduce(
8911
+ (sum, value) => sum + value.pendingRetirementBytes,
8912
+ 0
8913
+ );
8914
+ const peakBytes = Math.max(
8915
+ liveBytes + pendingRetirementBytes,
8916
+ ...inspections.map((value) => value.peakBytes)
8917
+ );
8918
+ return {
8919
+ unit: "engine-allocation-bytes",
8920
+ physicalResidency: "unknown",
8921
+ liveBytes,
8922
+ pendingRetirementBytes,
8923
+ peakBytes,
8924
+ successfulAllocationCount: inspections.reduce(
8925
+ (sum, value) => sum + value.successfulAllocationCount,
8926
+ 0
8927
+ ),
8928
+ successfulAllocationBytes: inspections.reduce(
8929
+ (sum, value) => sum + value.successfulAllocationBytes,
8930
+ 0
8931
+ ),
8932
+ pendingRetirementCount: inspections.reduce(
8933
+ (sum, value) => sum + value.pendingRetirementCount,
8934
+ 0
8935
+ ),
8936
+ retiredBytes: inspections.reduce((sum, value) => sum + value.retiredBytes, 0),
8937
+ failedAllocationRollbacks: inspections.reduce(
8938
+ (sum, value) => sum + value.failedAllocationRollbacks,
8939
+ 0
8940
+ ),
8941
+ failedAllocationRollbackBytes: inspections.reduce(
8942
+ (sum, value) => sum + value.failedAllocationRollbackBytes,
8943
+ 0
8944
+ )
8945
+ };
8946
+ }
8092
8947
 
8093
8948
  // src/scene/visibility/occlusion-confidence.ts
8094
8949
  function createConfidenceState() {
@@ -8440,6 +9295,7 @@ var COUNTER_WORDS = 2 + LOD_ROW_CAPACITY + 2;
8440
9295
  var GEOMETRY_WORK_COUNTER_OFFSET = 2 + LOD_ROW_CAPACITY;
8441
9296
  var ROOT_GEOMETRY_WORK_COUNTER_OFFSET = GEOMETRY_WORK_COUNTER_OFFSET + 1;
8442
9297
  var COUNTER_STRIDE = COUNTER_WORDS * 4;
9298
+ var INDIRECT_COMMAND_BYTES = 20;
8443
9299
  function selectGpuLodLane(caps) {
8444
9300
  return caps.compute && caps.storageBuffer && caps.indirectDrawing ? "gpu" : "cpu";
8445
9301
  }
@@ -8556,7 +9412,7 @@ fn selectLodLevel(
8556
9412
  @group(0) @binding(4) var<storage, read> batches: array<BatchRecord>;
8557
9413
  @group(0) @binding(5) var<uniform> view: ViewConstants;
8558
9414
  @group(0) @binding(6) var<storage, read_write> counters: array<atomic<u32>>;
8559
- @group(0) @binding(7) var<storage, read_write> visibleIndices: array<vec2<u32>>;
9415
+ @group(0) @binding(7) var<storage, read_write> visibleIndices: array<vec4<u32>>;
8560
9416
  @group(0) @binding(8) var<storage, read_write> indirectArgs: array<u32>;
8561
9417
 
8562
9418
  fn counterIndex(batchIndex: u32) -> u32 { return batchIndex * ${COUNTER_WORDS}u; }
@@ -8641,9 +9497,11 @@ fn cullView(@builtin(global_invocation_id) id: vec3<u32>) {
8641
9497
  if ((candidate.materialSlot & 0x80000000u) != 0u) {
8642
9498
  materialOrPalette = instance.customDataStart;
8643
9499
  }
8644
- visibleIndices[candidate.visibleBase + localVisible] = vec2<u32>(
9500
+ visibleIndices[candidate.visibleBase + localVisible] = vec4<u32>(
8645
9501
  candidate.submitAdmission >> 1u,
8646
9502
  materialOrPalette,
9503
+ candidate.primitiveIndex + 1u,
9504
+ candidate.generation,
8647
9505
  );
8648
9506
  }
8649
9507
 
@@ -8666,10 +9524,22 @@ fn finalizeView(@builtin(global_invocation_id) id: vec3<u32>) {
8666
9524
  let candidate = candidates[batch.candidateBase];
8667
9525
  let selectedLod = selectLodLevel(candidate.projectedHeight, candidate.previousLevel, candidate.historyValid != 0u, candidate.lodRows, candidate.lodCount);
8668
9526
  let lod = candidate.lodRows[selectedLod];
8669
- indirectArgs[args] = select(batch.count, lod.indexCount, candidate.lodCount > 0u);
9527
+ var drawCount = batch.count;
9528
+ var drawFirst = batch.first;
9529
+ var drawBaseVertex: i32 = 0;
9530
+ if (candidate.lodCount > 0u) {
9531
+ drawCount = lod.indexCount;
9532
+ if (batch.indexed != 0u) {
9533
+ drawFirst = lod.firstIndex;
9534
+ drawBaseVertex = lod.baseVertex;
9535
+ }
9536
+ } else if (batch.indexed != 0u) {
9537
+ drawBaseVertex = batch.baseVertex;
9538
+ }
9539
+ indirectArgs[args] = drawCount;
8670
9540
  indirectArgs[args + 1u] = visibleCount;
8671
- indirectArgs[args + 2u] = select(batch.first, lod.firstIndex, candidate.lodCount > 0u && batch.indexed != 0u);
8672
- indirectArgs[args + 3u] = select(0u, bitcast<u32>(lod.baseVertex), candidate.lodCount > 0u && batch.indexed != 0u);
9541
+ indirectArgs[args + 2u] = drawFirst;
9542
+ indirectArgs[args + 3u] = bitcast<u32>(drawBaseVertex);
8673
9543
  indirectArgs[args + 4u] = 0u;
8674
9544
  }
8675
9545
  `
@@ -8731,11 +9601,18 @@ var GpuDrivenView = class _GpuDrivenView {
8731
9601
  bindGroupCreates = 0;
8732
9602
  bufferRebuilds = 0;
8733
9603
  resourceGeneration = 0;
9604
+ allocationLedger = new GpuResourceAllocationLedger();
9605
+ allocationTokens = /* @__PURE__ */ new WeakMap();
8734
9606
  /** The last readback copy that was actually encoded and is not consumed. */
8735
9607
  telemetryPending;
9608
+ /** Receipt identity for the copy pass encoded by the current frame. */
9609
+ telemetrySubmit;
8736
9610
  /** Coalesce observers while the readback buffer is map-pending. */
8737
9611
  lodSelectionReadback;
8738
9612
  lodSelection;
9613
+ setTelemetrySubmit(identity) {
9614
+ this.telemetrySubmit = identity;
9615
+ }
8739
9616
  static create(input) {
8740
9617
  const { device, shaderModuleFactory } = input;
8741
9618
  const labelPrefix = input.labelPrefix ?? "gpu-driven-view";
@@ -8966,7 +9843,8 @@ var GpuDrivenView = class _GpuDrivenView {
8966
9843
  viewConstantsUploadBytes: this.viewConstantsUploadBytes,
8967
9844
  bindGroupCreates: this.bindGroupCreates,
8968
9845
  bufferRebuilds: this.bufferRebuilds,
8969
- resourceGeneration: this.resourceGeneration
9846
+ resourceGeneration: this.resourceGeneration,
9847
+ resourceAllocation: this.allocationLedger.inspect()
8970
9848
  };
8971
9849
  }
8972
9850
  get visibleBuffer() {
@@ -9011,6 +9889,7 @@ var GpuDrivenView = class _GpuDrivenView {
9011
9889
  let overflow = false;
9012
9890
  let geometryWork = 0;
9013
9891
  let rootGeometryWork = 0;
9892
+ const actualMembers = [];
9014
9893
  const histogram = /* @__PURE__ */ new Map();
9015
9894
  for (let batchIndex = 0; batchIndex < plan.batches.length; batchIndex += 1) {
9016
9895
  const offset = batchIndex * COUNTER_STRIDE;
@@ -9019,6 +9898,26 @@ var GpuDrivenView = class _GpuDrivenView {
9019
9898
  values.getUint32(offset, true),
9020
9899
  plan.batches[batchIndex]?.visibleCapacity ?? 0
9021
9900
  );
9901
+ const batch = plan.batches[batchIndex];
9902
+ const admitted = batch?.candidates.filter(
9903
+ (candidate) => candidate.submitAdmission !== false
9904
+ ) ?? [];
9905
+ for (let visibleIndex = 0; visibleIndex < batchVisible; visibleIndex += 1) {
9906
+ const visibleOffset = this.batchCapacity * COUNTER_STRIDE + ((batch?.visibleBase ?? 0) + visibleIndex) * 16;
9907
+ const projectionIndex = values.getUint32(visibleOffset, true);
9908
+ const primitiveIndex = values.getUint32(visibleOffset + 8, true) - 1;
9909
+ const generation = values.getUint32(visibleOffset + 12, true);
9910
+ const candidate = admitted[projectionIndex];
9911
+ if (batch !== void 0 && candidate !== void 0 && candidate.primitiveIndex === primitiveIndex && candidate.generation === generation) {
9912
+ actualMembers.push({
9913
+ batchId: batch.batchId,
9914
+ primitiveIndex,
9915
+ generation,
9916
+ drawItemIndex: candidate.drawItemIndex,
9917
+ instanceOrdinal: candidate.instanceOrdinal
9918
+ });
9919
+ }
9920
+ }
9022
9921
  visible += batchVisible;
9023
9922
  overflow ||= batchOverflow;
9024
9923
  geometryWork += values.getUint32(offset + GEOMETRY_WORK_COUNTER_OFFSET * 4, true);
@@ -9032,7 +9931,16 @@ var GpuDrivenView = class _GpuDrivenView {
9032
9931
  return void 0;
9033
9932
  }
9034
9933
  const candidateCount = plan.candidateCount;
9934
+ const surfaceReadback = copy.surfaceReadbackSnapshot?.();
9935
+ const surfaceIndirectReadback = surfaceReadback === void 0 ? void 0 : decodeSurfaceIndirectParameters({
9936
+ bytes: range.value,
9937
+ byteOffset: copy.indirectReadbackOffset,
9938
+ byteLength: this.indirectCapacity * INDIRECT_COMMAND_BYTES,
9939
+ indirectBufferIdentity: copy.indirectBufferIdentity,
9940
+ recording: surfaceReadback
9941
+ });
9035
9942
  this.lodSelection = Object.freeze({
9943
+ resourceGeneration: copy.resourceGeneration,
9036
9944
  candidateCount,
9037
9945
  batchCount: plan.batches.length,
9038
9946
  // Selector-only batches remain in the plan/readback but the production
@@ -9073,7 +9981,11 @@ var GpuDrivenView = class _GpuDrivenView {
9073
9981
  })
9074
9982
  ),
9075
9983
  geometryWork,
9076
- rootGeometryWork
9984
+ rootGeometryWork,
9985
+ actualMembers: Object.freeze(actualMembers),
9986
+ ...surfaceReadback === void 0 ? {} : { surfaceReadback },
9987
+ ...surfaceIndirectReadback === void 0 ? {} : surfaceIndirectReadback.ok ? { surfaceIndirectParameters: surfaceIndirectReadback.value } : { surfaceIndirectReadbackError: surfaceIndirectReadback.error },
9988
+ ...copy.submit === void 0 ? {} : { submit: copy.submit }
9077
9989
  });
9078
9990
  this.telemetryPending = void 0;
9079
9991
  return this.lodSelection;
@@ -9081,7 +9993,7 @@ var GpuDrivenView = class _GpuDrivenView {
9081
9993
  mapped.value.unmap();
9082
9994
  }
9083
9995
  }
9084
- addPasses(builder, labelPrefix = "gpu-driven", includeCompute = true) {
9996
+ addPasses(builder, labelPrefix = "gpu-driven", includeCompute = true, surfaceSubmissionObservation) {
9085
9997
  const buffers = this.buffers;
9086
9998
  const bindGroup = this.bindGroup;
9087
9999
  const plan = this.plan;
@@ -9161,14 +10073,14 @@ var GpuDrivenView = class _GpuDrivenView {
9161
10073
  const lodReadback = importBuffer(
9162
10074
  `${labelPrefix}.lod-selection-readback`,
9163
10075
  buffers.lodReadback,
9164
- this.batchCapacity * COUNTER_STRIDE,
10076
+ this.batchCapacity * COUNTER_STRIDE + this.visibleBufferCapacity * 16 + this.indirectCapacity * INDIRECT_COMMAND_BYTES,
9165
10077
  GPU_BUFFER_USAGE_MAP_READ | GPU_BUFFER_USAGE_COPY_DST
9166
10078
  );
9167
10079
  if (!lodReadback.ok) return lodReadback;
9168
10080
  const visible = importBuffer(
9169
10081
  `${labelPrefix}.visible`,
9170
10082
  buffers.visible,
9171
- this.visibleBufferCapacity * 8,
10083
+ this.visibleBufferCapacity * 16,
9172
10084
  GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC
9173
10085
  );
9174
10086
  if (!visible.ok) return visible;
@@ -9234,9 +10146,13 @@ var GpuDrivenView = class _GpuDrivenView {
9234
10146
  });
9235
10147
  if (!finalize.ok) return finalize;
9236
10148
  const graphResourceGeneration = this.resourceGeneration;
10149
+ const indirectReadbackOffset = this.batchCapacity * COUNTER_STRIDE + this.visibleBufferCapacity * 16;
10150
+ const indirectBufferIdentity = getOpaqueResourceIdentity(buffers.indirect);
9237
10151
  const readback = builder.addCopyPass(`${labelPrefix}.lod-selection-readback`, {
9238
10152
  accesses: [
9239
10153
  { resource: counters.value, usage: "copy-src" },
10154
+ { resource: visible.value, usage: "copy-src" },
10155
+ { resource: indirect.value, usage: "copy-src" },
9240
10156
  { resource: lodReadback.value, usage: "copy-dst" }
9241
10157
  ],
9242
10158
  encode: ({ encoder, resources }) => {
@@ -9247,12 +10163,33 @@ var GpuDrivenView = class _GpuDrivenView {
9247
10163
  resources.buffer(lodReadback.value).unwrap(),
9248
10164
  this.batchCapacity * COUNTER_STRIDE
9249
10165
  );
10166
+ encoder.copyBufferToBuffer(
10167
+ resources.buffer(visible.value).unwrap(),
10168
+ 0,
10169
+ resources.buffer(lodReadback.value).unwrap(),
10170
+ this.batchCapacity * COUNTER_STRIDE,
10171
+ this.visibleBufferCapacity * 16
10172
+ );
10173
+ encoder.copyBufferToBuffer(
10174
+ resources.buffer(indirect.value).unwrap(),
10175
+ 0,
10176
+ resources.buffer(lodReadback.value).unwrap(),
10177
+ indirectReadbackOffset,
10178
+ this.indirectCapacity * INDIRECT_COMMAND_BYTES
10179
+ );
9250
10180
  const submittedPlan = this.plan;
9251
10181
  if (this.buffers === buffers && submittedPlan !== void 0 && this.resourceGeneration === graphResourceGeneration) {
10182
+ const submittedObservation = surfaceSubmissionObservation?.();
9252
10183
  this.telemetryPending = {
9253
10184
  buffers,
9254
10185
  plan: submittedPlan,
9255
- resourceGeneration: graphResourceGeneration
10186
+ resourceGeneration: graphResourceGeneration,
10187
+ indirectBufferIdentity,
10188
+ indirectReadbackOffset,
10189
+ ...submittedObservation === void 0 ? {} : {
10190
+ surfaceReadbackSnapshot: () => submittedObservation.gpuReadbackSnapshot()
10191
+ },
10192
+ ...this.telemetrySubmit === void 0 ? {} : { submit: this.telemetrySubmit }
9256
10193
  };
9257
10194
  }
9258
10195
  }
@@ -9284,8 +10221,10 @@ var GpuDrivenView = class _GpuDrivenView {
9284
10221
  this.sceneMaterial = void 0;
9285
10222
  this.sceneCapacity = 0;
9286
10223
  this.telemetryPending = void 0;
10224
+ this.telemetrySubmit = void 0;
9287
10225
  this.lodSelectionReadback = void 0;
9288
10226
  this.lodSelection = void 0;
10227
+ for (const generation of buffers) this.retireGeneration(generation);
9289
10228
  this.destroyAfterSubmittedWork(buffers);
9290
10229
  void this.pipelineLayout;
9291
10230
  }
@@ -9322,6 +10261,7 @@ var GpuDrivenView = class _GpuDrivenView {
9322
10261
  const nextBatch = nextCapacity(batchCapacity);
9323
10262
  const nextIndirect = nextCapacity(indirectCapacity);
9324
10263
  const created = {};
10264
+ const createdTokens = [];
9325
10265
  const allocate = (name, size, usage) => {
9326
10266
  const buffer = this.device.createBuffer({
9327
10267
  label: `gpu-driven-view-${name}`,
@@ -9331,6 +10271,9 @@ var GpuDrivenView = class _GpuDrivenView {
9331
10271
  });
9332
10272
  if (!buffer.ok) return buffer;
9333
10273
  created[name] = buffer.value;
10274
+ const token = this.allocationLedger.allocate(size);
10275
+ this.allocationTokens.set(buffer.value, token);
10276
+ createdTokens.push(token);
9334
10277
  return ok$1(void 0);
9335
10278
  };
9336
10279
  const storage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC;
@@ -9354,7 +10297,7 @@ var GpuDrivenView = class _GpuDrivenView {
9354
10297
  storage: false
9355
10298
  },
9356
10299
  { name: "counters", size: nextBatch * COUNTER_STRIDE, usage: storage, storage: true },
9357
- { name: "visible", size: nextVisible * 8, usage: storage, storage: true },
10300
+ { name: "visible", size: nextVisible * 16, usage: storage, storage: true },
9358
10301
  {
9359
10302
  name: "indirect",
9360
10303
  size: nextIndirect * 20,
@@ -9363,7 +10306,7 @@ var GpuDrivenView = class _GpuDrivenView {
9363
10306
  },
9364
10307
  {
9365
10308
  name: "lodReadback",
9366
- size: nextBatch * COUNTER_STRIDE,
10309
+ size: nextBatch * COUNTER_STRIDE + nextVisible * 16 + nextIndirect * INDIRECT_COMMAND_BYTES,
9367
10310
  usage: GPU_BUFFER_USAGE_MAP_READ | GPU_BUFFER_USAGE_COPY_DST,
9368
10311
  storage: false
9369
10312
  }
@@ -9389,10 +10332,14 @@ var GpuDrivenView = class _GpuDrivenView {
9389
10332
  const result = allocate(request.name, request.size, request.usage);
9390
10333
  if (!result.ok) {
9391
10334
  for (const buffer of Object.values(created)) this.device.destroyBuffer(buffer);
10335
+ for (const token of createdTokens) this.allocationLedger.rollback(token);
9392
10336
  return result;
9393
10337
  }
9394
10338
  }
9395
- if (this.buffers !== void 0) this.supersededBuffers.push(this.buffers);
10339
+ if (this.buffers !== void 0) {
10340
+ this.supersededBuffers.push(this.buffers);
10341
+ this.retireGeneration(this.buffers);
10342
+ }
9396
10343
  this.buffers = created;
9397
10344
  this.candidateCapacity = nextCandidate;
9398
10345
  this.visibleBufferCapacity = nextVisible;
@@ -9409,11 +10356,19 @@ var GpuDrivenView = class _GpuDrivenView {
9409
10356
  for (const buffers of generations) {
9410
10357
  for (const buffer of Object.values(buffers)) {
9411
10358
  this.device.destroyBuffer(buffer);
10359
+ const token = this.allocationTokens.get(buffer);
10360
+ if (token !== void 0) this.allocationLedger.release(token);
9412
10361
  }
9413
10362
  }
9414
10363
  };
9415
10364
  void this.device.queue.onSubmittedWorkDone().then(release, release);
9416
10365
  }
10366
+ retireGeneration(generation) {
10367
+ for (const buffer of Object.values(generation)) {
10368
+ const token = this.allocationTokens.get(buffer);
10369
+ if (token !== void 0) this.allocationLedger.retire(token);
10370
+ }
10371
+ }
9417
10372
  };
9418
10373
 
9419
10374
  // src/gpu-driven/shadow-views.ts
@@ -9841,6 +10796,7 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
9841
10796
  );
9842
10797
  }
9843
10798
  const projectorAvailable = pipelineState.projectorAvailable !== false;
10799
+ const lowLimitCloudBindings = !extendedLighting && !projectorAvailable;
9844
10800
  try {
9845
10801
  return getOrCreateFromChain(
9846
10802
  frameState.viewBindGroupCache,
@@ -9853,7 +10809,8 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
9853
10809
  pipelineState.shadowCasterCascadeBuffer,
9854
10810
  pipelineState.shadowFallbackTextureView,
9855
10811
  ...extendedLighting ? extendedLightingCacheKeys : projectorAvailable ? [pipelineState.defaultWhiteTextureView, pipelineState.defaultSampler] : [],
9856
- pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer
10812
+ pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
10813
+ ...lowLimitCloudBindings ? [] : [pipelineState.defaultWhiteTextureView, pipelineState.defaultSampler]
9857
10814
  ],
9858
10815
  variant,
9859
10816
  () => {
@@ -9929,7 +10886,23 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
9929
10886
  binding: 12,
9930
10887
  resource: { kind: "sampler", value: pipelineState.defaultSampler }
9931
10888
  }
9932
- ] : []
10889
+ ] : [],
10890
+ ...lowLimitCloudBindings ? [] : [
10891
+ {
10892
+ binding: 16,
10893
+ resource: {
10894
+ kind: "textureView",
10895
+ value: pipelineState.defaultWhiteTextureView
10896
+ }
10897
+ },
10898
+ {
10899
+ binding: 17,
10900
+ resource: {
10901
+ kind: "sampler",
10902
+ value: pipelineState.defaultSampler
10903
+ }
10904
+ }
10905
+ ]
9933
10906
  ]
9934
10907
  });
9935
10908
  if (!created.ok) throw created.error;
@@ -10308,6 +11281,7 @@ function recordGpuDrivenShadowIfPublished(c, pass, identity) {
10308
11281
  visibleBindGroup: projection.visibleBindGroup,
10309
11282
  deformation: projection.deformation,
10310
11283
  materialGroup,
11284
+ ...batch.key.admission === "alpha-mask" ? { alphaMaskMaterialGroup: materialGroup } : {},
10311
11285
  vertexBuffer: projection.mesh.vertexBuffer.handle,
10312
11286
  ...batch.key.drawKind === "indexed" && projection.mesh.indexBuffer !== null ? {
10313
11287
  indexBuffer: projection.mesh.indexBuffer.handle,
@@ -10853,7 +11827,12 @@ function recordShadowCasterDraws(c, shadowPass, shadowPipeline2, shadowMeshBindG
10853
11827
  }
10854
11828
  } else {
10855
11829
  const bufUsage = uniformFallback ? GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST : GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
10856
- const instancePayload = uniformFallback ? shadowInst.transforms : packInstanceStorageBuffer(shadowInst.transforms);
11830
+ const instancePayload = uniformFallback ? shadowInst.transforms : packInstanceStorageBuffer(
11831
+ shadowInst.transforms,
11832
+ entry.source.temporal?.previousInstances?.transforms,
11833
+ shadowInst.generations,
11834
+ entry.source.temporal?.previousInstances?.generations
11835
+ );
10857
11836
  const requestedBytes = instancePayload.byteLength;
10858
11837
  const cap = runtime.device.limits.maxStorageBufferBindingSize;
10859
11838
  if (!uniformFallback && typeof cap === "number" && cap > 0 && requestedBytes > cap) {
@@ -11217,7 +12196,10 @@ function ensureGpuDrivenAlphaMaskMaterialBg(c, projection) {
11217
12196
  return bindGroup;
11218
12197
  }
11219
12198
  function ensureGpuDrivenCustomShadowMaterialBg(c, projection) {
11220
- const shaderId = projection.shadowArtifact.material;
12199
+ const shaderId = projection.shadowArtifact.specializationKey ?? projection.shadowArtifact.material;
12200
+ const materialKey = `shadow-material-custom:${shaderId}:${projection.materialEntityKey}:${projection.material.materialHandle ?? -1}:${c.store.materialResourceEpoch}`;
12201
+ const cached = c.materialBgAssemblyCache.get(materialKey);
12202
+ if (cached !== void 0) return cached.bindGroup;
11221
12203
  const fallback = c.pipelineState.skylightFallback;
11222
12204
  if (fallback === null) {
11223
12205
  throw new RhiError({
@@ -11279,18 +12261,23 @@ function isTransmissionMaterial(material) {
11279
12261
  return material.materialShaderId === "forgeax::default-standard-pbr" && typeof material.paramSnapshot?.transmission === "number" && material.paramSnapshot.transmission > 0;
11280
12262
  }
11281
12263
  function matchesRecordMode(material, mode) {
12264
+ const medium = material.surfaceModel === "single-layer-medium" || material.materialShaderId === "forgeax::single-layer-medium";
12265
+ if (mode === "single-layer-medium-nearest-layer" || mode === "single-layer-medium-color") {
12266
+ return medium;
12267
+ }
11282
12268
  const transmission = isTransmissionMaterial(material);
11283
12269
  if (mode === "transmission") return transmission;
11284
- if (mode === "transparent") return material.transparent === true && !transmission;
11285
- return !transmission && material.transparent !== true;
12270
+ if (mode === "transparent") return material.transparent === true && !transmission && !medium;
12271
+ return !transmission && material.transparent !== true && !medium;
11286
12272
  }
11287
12273
  function matchedMaterialsForRecordMode(c, matchedMaterials, mode) {
11288
12274
  if (mode === void 0) return matchedMaterials;
12275
+ const surfaceMode = mode === "single-layer-medium-nearest-layer" || mode === "single-layer-medium-color";
11289
12276
  const filtered = /* @__PURE__ */ new Map();
11290
12277
  for (const entry of c.validatedOrdered) {
11291
12278
  const dispatchHandles = matchedMaterials?.get(entry.renderableIndex);
11292
- if (matchedMaterials !== null && dispatchHandles === void 0) continue;
11293
- const candidateHandles = dispatchHandles ?? (mode === "transmission" ? [] : entry.source.materials.map((material) => material.materialHandle ?? 0));
12279
+ if (!surfaceMode && matchedMaterials !== null && dispatchHandles === void 0) continue;
12280
+ const candidateHandles = surfaceMode ? entry.source.materials.map((material) => material.materialHandle ?? 0) : dispatchHandles ?? (mode === "transmission" ? [] : entry.source.materials.map((material) => material.materialHandle ?? 0));
11294
12281
  const handles = /* @__PURE__ */ new Set();
11295
12282
  for (const handle of candidateHandles) {
11296
12283
  const material = entry.source.materials.find((candidate) => (candidate.materialHandle ?? 0) === handle) ?? entry.source.material;
@@ -11333,11 +12320,14 @@ function recordMainPass(c, selector, options, graphPass) {
11333
12320
  const passKind = options?.passKind ?? "forward";
11334
12321
  const recordMode = options?.recordMode;
11335
12322
  const transmissionBackdropView = options?.transmissionBackdropView;
11336
- if (recordMode === "transmission" && transmissionBackdropView == null) {
12323
+ const surfaceRawDepthView = options?.surfaceRawDepthView;
12324
+ const surfaceNearestLayerView = options?.surfaceNearestLayerView;
12325
+ const surfaceNearestDepthView = options?.surfaceNearestDepthView;
12326
+ if ((recordMode === "transmission" || recordMode === "single-layer-medium-nearest-layer" || recordMode === "single-layer-medium-color") && transmissionBackdropView == null) {
11337
12327
  throw new RhiError({
11338
12328
  code: "webgpu-runtime-error",
11339
- expected: "transmissionBackdropView != null for transmission record mode",
11340
- hint: "the typed Standard transmission pass must resolve its private backdrop view"
12329
+ expected: "transmissionBackdropView != null for a backdrop-consuming record mode",
12330
+ hint: "the typed Standard backdrop pass must resolve its graph-paired color view"
11341
12331
  });
11342
12332
  }
11343
12333
  const colorViews = options?.colorViews ?? [geometryColorView];
@@ -11349,12 +12339,9 @@ function recordMainPass(c, selector, options, graphPass) {
11349
12339
  const videoHighPerfAvailable = probeVideoHighPerfUpload(runtime.device);
11350
12340
  const clusteredLighting = c.standardLighting?.kind === "clustered";
11351
12341
  const clusteredBindGroupMissing = validatedOrdered.length > 0 && !standardTopologyBindGroupReady(c.standardLighting, hdrpClusterBindGroup);
12342
+ const hdrpBuffers = clusteredLighting ? getOrCreateHdrpBuffers(runtime, frameState.installedPipelineConfig?.clusterGrid) : null;
11352
12343
  let hdrpSsaoBindGroup = null;
11353
- if (clusteredLighting && hdrpClusterBindGroup !== null && c.hdrpSsaoBlurredView !== void 0) {
11354
- const hdrpBuffers = getOrCreateHdrpBuffers(
11355
- runtime,
11356
- frameState.installedPipelineConfig?.clusterGrid
11357
- );
12344
+ if (hdrpClusterBindGroup !== null && c.hdrpSsaoBlurredView !== void 0) {
11358
12345
  if (hdrpBuffers !== null) {
11359
12346
  hdrpSsaoBindGroup = createHdrpUnifiedBindGroup(
11360
12347
  runtime,
@@ -11365,6 +12352,58 @@ function recordMainPass(c, selector, options, graphPass) {
11365
12352
  }
11366
12353
  }
11367
12354
  const meshGroup2 = clusteredLighting ? hdrpSsaoBindGroup ?? hdrpClusterBindGroup : meshBindGroup;
12355
+ if (gpuDrivenStandardPbrFrameResources !== void 0) {
12356
+ gpuDrivenStandardPbrFrameResources.clusterBindGroup = clusteredLighting && meshGroup2 !== null ? meshGroup2 : void 0;
12357
+ if (hdrpBuffers === null) {
12358
+ gpuDrivenStandardPbrFrameResources.clusterBindGroupForMesh = void 0;
12359
+ gpuDrivenStandardPbrFrameResources.clusterBindGroupForSkin = void 0;
12360
+ } else {
12361
+ const projectedGroups = /* @__PURE__ */ new Map();
12362
+ gpuDrivenStandardPbrFrameResources.clusterBindGroupForMesh = (meshBuffer, bindingBytes) => {
12363
+ const cached = projectedGroups.get(meshBuffer);
12364
+ if (cached !== void 0) return cached;
12365
+ const created = createHdrpUnifiedBindGroup(
12366
+ runtime,
12367
+ hdrpBuffers,
12368
+ meshBuffer,
12369
+ c.hdrpSsaoBlurredView === void 0 ? { enabled: false } : { enabled: true, ssaoBlurredView: c.hdrpSsaoBlurredView },
12370
+ bindingBytes
12371
+ );
12372
+ if (created !== null) projectedGroups.set(meshBuffer, created);
12373
+ return created ?? void 0;
12374
+ };
12375
+ const projectedSkinGroups = /* @__PURE__ */ new Map();
12376
+ gpuDrivenStandardPbrFrameResources.clusterBindGroupForSkin = (meshBuffer, meshBindingBytes, paletteBuffer, paletteBindingWindowBytes) => {
12377
+ let meshGroups = projectedSkinGroups.get(meshBuffer);
12378
+ if (meshGroups === void 0) {
12379
+ meshGroups = /* @__PURE__ */ new Map();
12380
+ projectedSkinGroups.set(meshBuffer, meshGroups);
12381
+ }
12382
+ let paletteGroups = meshGroups.get(paletteBuffer);
12383
+ if (paletteGroups === void 0) {
12384
+ paletteGroups = /* @__PURE__ */ new Map();
12385
+ meshGroups.set(paletteBuffer, paletteGroups);
12386
+ }
12387
+ const bindingKey = `${meshBindingBytes}:${paletteBindingWindowBytes}`;
12388
+ const cached = paletteGroups.get(bindingKey);
12389
+ if (cached !== void 0) return cached;
12390
+ const skinLayout = pipelineState.hdrpSkinMeshBindGroupLayout;
12391
+ if (skinLayout === null) return void 0;
12392
+ const created = createHdrpSkinUnifiedBindGroup(
12393
+ runtime,
12394
+ hdrpBuffers,
12395
+ skinLayout,
12396
+ meshBuffer,
12397
+ paletteBuffer,
12398
+ paletteBindingWindowBytes,
12399
+ c.hdrpSsaoBlurredView === void 0 ? { enabled: false } : { enabled: true, ssaoBlurredView: c.hdrpSsaoBlurredView },
12400
+ meshBindingBytes
12401
+ );
12402
+ if (created !== null) paletteGroups.set(bindingKey, created);
12403
+ return created ?? void 0;
12404
+ };
12405
+ }
12406
+ }
11368
12407
  let geometryPassEnded = false;
11369
12408
  const mainColorLoadOp = skyboxActive ? "load" : "clear";
11370
12409
  const mainPassResolves = passKind === "forward" && msaaActive && geometryColorResolveView !== null && !splitLdrSprite;
@@ -11522,7 +12561,10 @@ function recordMainPass(c, selector, options, graphPass) {
11522
12561
  ...gpuDrivenStandardPbrFrameResources?.sceneMaterialBuffer === void 0 && gpuDrivenSceneMaterialBuffer === void 0 ? {} : {
11523
12562
  sceneMaterialBuffer: gpuDrivenStandardPbrFrameResources?.sceneMaterialBuffer ?? gpuDrivenSceneMaterialBuffer
11524
12563
  },
11525
- ...transmissionBackdropView === void 0 ? {} : { transmissionBackdropView }
12564
+ ...transmissionBackdropView === void 0 ? {} : { transmissionBackdropView },
12565
+ ...surfaceRawDepthView === void 0 ? {} : { surfaceRawDepthView },
12566
+ ...surfaceNearestLayerView === void 0 ? {} : { surfaceNearestLayerView },
12567
+ ...surfaceNearestDepthView === void 0 ? {} : { surfaceNearestDepthView }
11526
12568
  };
11527
12569
  const buildPerSubmeshMaterialBg2 = (submeshMaterial, entityKey, materialWorld = world, materialShaderId = submeshMaterial.materialShaderId) => buildPerSubmeshMaterialBg(
11528
12570
  perSubmeshMaterialBgDeps,
@@ -11535,6 +12577,7 @@ function recordMainPass(c, selector, options, graphPass) {
11535
12577
  for (let materialSlot = 0; materialSlot < materialSlotCount; materialSlot += 1) {
11536
12578
  const material = materialSlots[materialSlot];
11537
12579
  if (material === void 0 || (material.videoTextureFields?.size ?? 0) > 0) continue;
12580
+ if (recordMode !== void 0 && !matchesRecordMode(material, recordMode)) continue;
11538
12581
  const owner = materialSlotOwners[materialSlot];
11539
12582
  if (owner === void 0) continue;
11540
12583
  preparedMaterialBindGroups[materialSlot] = buildPerSubmeshMaterialBg2(
@@ -11605,7 +12648,10 @@ function recordMainPass(c, selector, options, graphPass) {
11605
12648
  passKind,
11606
12649
  selectedDispatch,
11607
12650
  colorFormats,
11608
- options?.coverageOnly ?? false
12651
+ options?.coverageOnly ?? false,
12652
+ options?.fragmentEntryPoint,
12653
+ recordMode === "single-layer-medium-nearest-layer" ? "nearest-layer" : recordMode === "single-layer-medium-color" ? "color" : void 0,
12654
+ options?.transparentDepthWrite ?? false
11609
12655
  );
11610
12656
  };
11611
12657
  if (c.profilePhase === void 0) {
@@ -11625,7 +12671,7 @@ function recordMainPass(c, selector, options, graphPass) {
11625
12671
  hint: "publish the current frame view/light/shadow bind group before GPU raster"
11626
12672
  });
11627
12673
  }
11628
- if (gpuDrivenStandardPbrFrameResources === void 0) {
12674
+ if (gpuDrivenStandardPbrFrameResources === void 0 || gpuDrivenStandardPbrFrameResources.materialBindGroups.length === 0) {
11629
12675
  throw new RhiError({
11630
12676
  code: "rhi-not-available",
11631
12677
  expected: "complete main-pass Standard PBR material bind-group receipt",
@@ -11636,7 +12682,9 @@ function recordMainPass(c, selector, options, graphPass) {
11636
12682
  viewBindGroup,
11637
12683
  pass,
11638
12684
  options.gpuDriven.resources,
11639
- gpuDrivenStandardPbrFrameResources
12685
+ gpuDrivenStandardPbrFrameResources,
12686
+ options.gpuDrivenFilter,
12687
+ options?.fragmentEntryPoint
11640
12688
  );
11641
12689
  }
11642
12690
  if (passKind === "forward" && recordMode === void 0) {
@@ -11660,6 +12708,27 @@ function recordMainPass(c, selector, options, graphPass) {
11660
12708
  function encodeMainPass(c, pass, selector, options) {
11661
12709
  return recordMainPass(c, selector, options, pass);
11662
12710
  }
12711
+
12712
+ // src/assembly/webgpu-ready-contract.ts
12713
+ var VIEW_UBO_BYTES = VIEW_UNIFORM_BUFFER_SIZE;
12714
+ var MIPMAP_PREWARM_FORMATS = [
12715
+ "rgba8unorm-srgb",
12716
+ "rgba8unorm",
12717
+ "rgba16float"
12718
+ ];
12719
+ var BLOOM_UNIFORM_PARAMS_STRIDE_BYTES = 256;
12720
+ var BLOOM_DOWNSAMPLE_PARAMS_BYTES = 5 * BLOOM_UNIFORM_PARAMS_STRIDE_BYTES;
12721
+ var BLOOM_UPSAMPLE_PARAMS_BYTES = 4 * BLOOM_UNIFORM_PARAMS_STRIDE_BYTES;
12722
+ var BLOOM_COMPOSITE_PARAMS_BYTES = 16;
12723
+ var HDR_COLOR_ATTACHMENT_FORMAT = "rgba16float";
12724
+ var DEPTH_TEXTURE_FORMAT = "depth24plus-stencil8";
12725
+
12726
+ // src/bloom-admission.ts
12727
+ function standardBloomAdmitted(camera) {
12728
+ return camera !== void 0 && camera.bloom === "on" && camera.bloomIntensity > 0 && camera.tonemap !== "none";
12729
+ }
12730
+
12731
+ // src/record/skybox-post-pass.ts
11663
12732
  function recordSkyboxPass(c, graphPass) {
11664
12733
  if (!c.skyboxActive) return;
11665
12734
  const skyboxSnapshot = c.skybox;
@@ -11767,179 +12836,138 @@ function throwBloomRecordFailure(expected) {
11767
12836
  hint: "repair the Bloom candidate resources before retrying the frame"
11768
12837
  });
11769
12838
  }
11770
- function recordBloomBrightPass(_c, resolve, graphPass) {
11771
- const { runtime, encoder, camera, tonemapActive, frameState, bindGroupCounts } = _c;
11772
- const pp = _c.bloomResources;
11773
- if (camera.bloom !== "on" || !tonemapActive) return;
11774
- if (pp === null || pp === void 0) {
11775
- throwBloomRecordFailure("Bloom persistent resources are ready before bright-pass encoding");
11776
- }
11777
- if (pp.bloomBrightPipeline === null || pp.bloomBrightBindGroupLayout === null || pp.bloomSampler === null || pp.bloomBrightParamsBuffer === null) {
11778
- throwBloomRecordFailure("Bloom bright pass has pipeline, layout, sampler, and params buffer");
11779
- }
11780
- const bloomBrightView = resolve?.resolve("bloomBright");
11781
- const hdrColorView = resolve?.resolve("hdrColor");
11782
- if (!bloomBrightView || !hdrColorView) {
11783
- throwBloomRecordFailure("Bloom bright pass resolves its source and target views");
11784
- }
11785
- const bglBright = pp.bloomBrightBindGroupLayout;
11786
- const bloomSampler = pp.bloomSampler;
11787
- const paramsBuffer = pp.bloomBrightParamsBuffer;
11788
- const brightParams = new Float32Array(4);
11789
- brightParams[0] = camera.bloomThreshold;
11790
- brightParams[1] = 0;
11791
- brightParams[2] = 0;
11792
- brightParams[3] = 0;
11793
- const paramsWrite = runtime.device.queue.writeBuffer(paramsBuffer, 0, brightParams);
11794
- if (!paramsWrite.ok) throw paramsWrite.error;
11795
- stageBloomUpload(_c);
11796
- const bindGroup = getOrCreateFromChain(
11797
- frameState.postProcessBgCache,
11798
- [hdrColorView],
11799
- "bloom-bright",
11800
- () => {
11801
- const bgRes = runtime.device.createBindGroup({
11802
- label: "bloom-bright-bg",
11803
- layout: bglBright,
11804
- entries: [
11805
- { binding: 0, resource: { kind: "textureView", value: hdrColorView } },
11806
- { binding: 1, resource: { kind: "sampler", value: bloomSampler } },
11807
- { binding: 2, resource: { kind: "buffer", value: { buffer: paramsBuffer } } }
11808
- ]
11809
- });
11810
- if (!bgRes.ok) throw bgRes.error;
11811
- return bgRes.value;
11812
- },
11813
- bindGroupCounts
11814
- );
11815
- const pass = graphPass ?? encoder.beginRenderPass(
11816
- buildBeginRenderPassDescriptor(
11817
- { depthFormat: void 0},
11818
- { colorViews: [bloomBrightView] },
11819
- "bloom-bright"
11820
- )
11821
- );
11822
- pass.setPipeline(pp.bloomBrightPipeline);
11823
- pass.setBindGroup(0, bindGroup);
11824
- stageBloomBindGroup(_c);
11825
- pass.draw(3, 1, 0, 0);
11826
- stageBloomEncode(_c);
11827
- if (graphPass === void 0) pass.end();
12839
+ function bloomRecordActive(c) {
12840
+ return standardBloomAdmitted(c.camera) && c.tonemapActive;
11828
12841
  }
11829
- function recordBloomBlurHPass(_c, resolve, graphPass) {
11830
- const { runtime, encoder, camera, targetW, tonemapActive, frameState, bindGroupCounts } = _c;
12842
+ function recordBloomDownsamplePass(_c, resolve, graphPass, level = 0, destinationSize) {
12843
+ const { runtime, encoder, camera, frameState, bindGroupCounts } = _c;
11831
12844
  const pp = _c.bloomResources;
11832
- if (camera.bloom !== "on" || !tonemapActive) return;
11833
- if (pp === null || pp === void 0) {
11834
- throwBloomRecordFailure("Bloom persistent resources are ready before blur-H encoding");
11835
- }
11836
- if (pp.bloomBlurHPipeline === null || pp.bloomBlurBindGroupLayout === null || pp.bloomSampler === null || pp.bloomBlurHParamsBuffer === null) {
11837
- throwBloomRecordFailure("Bloom blur-H pass has pipeline, layout, sampler, and params buffer");
12845
+ if (!bloomRecordActive(_c)) return;
12846
+ if (pp === void 0 || pp === null || pp.bloomDownsamplePipeline === null || pp.bloomDownsampleBindGroupLayout === null || pp.bloomSampler === null || pp.bloomDownsampleParamsBuffer === null) {
12847
+ throwBloomRecordFailure("Bloom downsample resources are ready before encoding");
11838
12848
  }
11839
- const bloomBlurHView = resolve?.resolve("bloomBlurH");
11840
- const bloomBrightView = resolve?.resolve("bloomBright");
11841
- if (!bloomBlurHView || !bloomBrightView) {
11842
- throwBloomRecordFailure("Bloom blur-H pass resolves its source and target views");
11843
- }
11844
- const bglBlur = pp.bloomBlurBindGroupLayout;
12849
+ const downsamplePipeline = pp.bloomDownsamplePipeline;
12850
+ const downsampleLayout = pp.bloomDownsampleBindGroupLayout;
11845
12851
  const bloomSampler = pp.bloomSampler;
11846
- const paramsBuffer = pp.bloomBlurHParamsBuffer;
11847
- const bw = Math.floor(targetW / 2);
11848
- const blurParams = new Float32Array(4);
11849
- blurParams[0] = bw > 0 ? 1 / bw : 1;
11850
- blurParams[1] = 0;
11851
- blurParams[2] = camera.bloomBlurRadius;
11852
- blurParams[3] = 0;
11853
- const paramsWrite = runtime.device.queue.writeBuffer(paramsBuffer, 0, blurParams);
11854
- if (!paramsWrite.ok) throw paramsWrite.error;
12852
+ const downsampleParamsBuffer = pp.bloomDownsampleParamsBuffer;
12853
+ const sourceName = level === 0 ? "hdrColor" : `bloomDownsample${level - 1}`;
12854
+ const targetName = `bloomDownsample${level}`;
12855
+ const sourceView = resolve?.resolve(sourceName);
12856
+ const targetView = resolve?.resolve(targetName);
12857
+ if (sourceView === void 0 || targetView === void 0) {
12858
+ throwBloomRecordFailure(`Bloom downsample level ${level} resolves source and target views`);
12859
+ }
12860
+ const size = destinationSize ?? {
12861
+ width: Math.max(1, Math.ceil(_c.targetW / 2)),
12862
+ height: Math.max(1, Math.ceil(_c.targetH / 2))
12863
+ };
12864
+ const params = new Float32Array([
12865
+ camera.bloomThreshold,
12866
+ camera.bloomSoftKnee,
12867
+ size.width,
12868
+ size.height,
12869
+ level,
12870
+ 0,
12871
+ 0,
12872
+ 0
12873
+ ]);
12874
+ const offset = level * BLOOM_UNIFORM_PARAMS_STRIDE_BYTES;
12875
+ const upload = runtime.device.queue.writeBuffer(pp.bloomDownsampleParamsBuffer, offset, params);
12876
+ if (!upload.ok) throw upload.error;
11855
12877
  stageBloomUpload(_c);
11856
12878
  const bindGroup = getOrCreateFromChain(
11857
12879
  frameState.postProcessBgCache,
11858
- [bloomBrightView],
11859
- "bloom-blur-h",
12880
+ [sourceView, downsampleParamsBuffer],
12881
+ `bloom-downsample-${level}`,
11860
12882
  () => {
11861
- const bgRes = runtime.device.createBindGroup({
11862
- label: "bloom-blur-h-bg",
11863
- layout: bglBlur,
12883
+ const created = runtime.device.createBindGroup({
12884
+ label: `bloom-downsample-${level}-bg`,
12885
+ layout: downsampleLayout,
11864
12886
  entries: [
11865
- { binding: 0, resource: { kind: "textureView", value: bloomBrightView } },
12887
+ { binding: 0, resource: { kind: "textureView", value: sourceView } },
11866
12888
  { binding: 1, resource: { kind: "sampler", value: bloomSampler } },
11867
- { binding: 2, resource: { kind: "buffer", value: { buffer: paramsBuffer } } }
12889
+ {
12890
+ binding: 2,
12891
+ resource: {
12892
+ kind: "buffer",
12893
+ value: { buffer: downsampleParamsBuffer, offset, size: 32 }
12894
+ }
12895
+ }
11868
12896
  ]
11869
12897
  });
11870
- if (!bgRes.ok) throw bgRes.error;
11871
- return bgRes.value;
12898
+ if (!created.ok) throw created.error;
12899
+ return created.value;
11872
12900
  },
11873
12901
  bindGroupCounts
11874
12902
  );
11875
12903
  const pass = graphPass ?? encoder.beginRenderPass(
11876
12904
  buildBeginRenderPassDescriptor(
11877
12905
  { depthFormat: void 0},
11878
- { colorViews: [bloomBlurHView] },
11879
- "bloom-blur"
12906
+ { colorViews: [targetView] },
12907
+ "bloom-downsample"
11880
12908
  )
11881
12909
  );
11882
- pass.setPipeline(pp.bloomBlurHPipeline);
12910
+ pass.setPipeline(downsamplePipeline);
11883
12911
  pass.setBindGroup(0, bindGroup);
11884
12912
  stageBloomBindGroup(_c);
11885
12913
  pass.draw(3, 1, 0, 0);
11886
12914
  stageBloomEncode(_c);
11887
12915
  if (graphPass === void 0) pass.end();
11888
12916
  }
11889
- function recordBloomBlurVPass(_c, resolve, graphPass) {
11890
- const { runtime, encoder, camera, targetH, tonemapActive, frameState, bindGroupCounts } = _c;
12917
+ function recordBloomUpsamplePass(_c, resolve, graphPass, level = 0) {
12918
+ const { runtime, encoder, frameState, bindGroupCounts } = _c;
11891
12919
  const pp = _c.bloomResources;
11892
- if (camera.bloom !== "on" || !tonemapActive) return;
11893
- if (pp === null || pp === void 0) {
11894
- throwBloomRecordFailure("Bloom persistent resources are ready before blur-V encoding");
11895
- }
11896
- if (pp.bloomBlurVPipeline === null || pp.bloomBlurBindGroupLayout === null || pp.bloomSampler === null || pp.bloomBlurVParamsBuffer === null) {
11897
- throwBloomRecordFailure("Bloom blur-V pass has pipeline, layout, sampler, and params buffer");
12920
+ if (!bloomRecordActive(_c)) return;
12921
+ if (pp === void 0 || pp === null || pp.bloomUpsamplePipeline === null || pp.bloomUpsampleBindGroupLayout === null || pp.bloomSampler === null || pp.bloomUpsampleParamsBuffer === null) {
12922
+ throwBloomRecordFailure("Bloom upsample resources are ready before encoding");
11898
12923
  }
11899
- const bloomBlurVView = resolve?.resolve("bloomBlurV");
11900
- const bloomBlurHView = resolve?.resolve("bloomBlurH");
11901
- if (!bloomBlurVView || !bloomBlurHView) {
11902
- throwBloomRecordFailure("Bloom blur-V pass resolves its source and target views");
11903
- }
11904
- const bglBlur = pp.bloomBlurBindGroupLayout;
12924
+ const upsamplePipeline = pp.bloomUpsamplePipeline;
12925
+ const upsampleLayout = pp.bloomUpsampleBindGroupLayout;
11905
12926
  const bloomSampler = pp.bloomSampler;
11906
- const paramsBuffer = pp.bloomBlurVParamsBuffer;
11907
- const bh = Math.floor(targetH / 2);
11908
- const blurParams = new Float32Array(4);
11909
- blurParams[0] = 0;
11910
- blurParams[1] = bh > 0 ? 1 / bh : 1;
11911
- blurParams[2] = camera.bloomBlurRadius;
11912
- blurParams[3] = 0;
11913
- const paramsWrite = runtime.device.queue.writeBuffer(paramsBuffer, 0, blurParams);
11914
- if (!paramsWrite.ok) throw paramsWrite.error;
12927
+ const upsampleParamsBuffer = pp.bloomUpsampleParamsBuffer;
12928
+ const currentView = resolve?.resolve(`bloomDownsample${level}`);
12929
+ const nextUpsampleView = resolve?.resolve(`bloomUpsample${level + 1}`);
12930
+ const coarseView = nextUpsampleView ?? resolve?.resolve(`bloomDownsample${level + 1}`);
12931
+ const targetView = resolve?.resolve(`bloomUpsample${level}`);
12932
+ if (currentView === void 0 || coarseView === void 0 || targetView === void 0) {
12933
+ throwBloomRecordFailure(`Bloom upsample level ${level} resolves adjacent pyramid views`);
12934
+ }
12935
+ const params = new Float32Array([_c.camera.bloomScatter, 0, 0, 0]);
12936
+ const offset = level * BLOOM_UNIFORM_PARAMS_STRIDE_BYTES;
12937
+ const upload = runtime.device.queue.writeBuffer(pp.bloomUpsampleParamsBuffer, offset, params);
12938
+ if (!upload.ok) throw upload.error;
11915
12939
  stageBloomUpload(_c);
11916
12940
  const bindGroup = getOrCreateFromChain(
11917
12941
  frameState.postProcessBgCache,
11918
- [bloomBlurHView],
11919
- "bloom-blur-v",
12942
+ [currentView, coarseView, upsampleParamsBuffer],
12943
+ `bloom-upsample-${level}`,
11920
12944
  () => {
11921
- const bgRes = runtime.device.createBindGroup({
11922
- label: "bloom-blur-v-bg",
11923
- layout: bglBlur,
12945
+ const created = runtime.device.createBindGroup({
12946
+ label: `bloom-upsample-${level}-bg`,
12947
+ layout: upsampleLayout,
11924
12948
  entries: [
11925
- { binding: 0, resource: { kind: "textureView", value: bloomBlurHView } },
11926
- { binding: 1, resource: { kind: "sampler", value: bloomSampler } },
11927
- { binding: 2, resource: { kind: "buffer", value: { buffer: paramsBuffer } } }
12949
+ { binding: 0, resource: { kind: "textureView", value: currentView } },
12950
+ { binding: 1, resource: { kind: "textureView", value: coarseView } },
12951
+ { binding: 2, resource: { kind: "sampler", value: bloomSampler } },
12952
+ {
12953
+ binding: 3,
12954
+ resource: { kind: "buffer", value: { buffer: upsampleParamsBuffer, offset, size: 16 } }
12955
+ }
11928
12956
  ]
11929
12957
  });
11930
- if (!bgRes.ok) throw bgRes.error;
11931
- return bgRes.value;
12958
+ if (!created.ok) throw created.error;
12959
+ return created.value;
11932
12960
  },
11933
12961
  bindGroupCounts
11934
12962
  );
11935
12963
  const pass = graphPass ?? encoder.beginRenderPass(
11936
12964
  buildBeginRenderPassDescriptor(
11937
12965
  { depthFormat: void 0},
11938
- { colorViews: [bloomBlurVView] },
11939
- "bloom-blur"
12966
+ { colorViews: [targetView] },
12967
+ "bloom-upsample"
11940
12968
  )
11941
12969
  );
11942
- pass.setPipeline(pp.bloomBlurVPipeline);
12970
+ pass.setPipeline(upsamplePipeline);
11943
12971
  pass.setBindGroup(0, bindGroup);
11944
12972
  stageBloomBindGroup(_c);
11945
12973
  pass.draw(3, 1, 0, 0);
@@ -11947,9 +12975,9 @@ function recordBloomBlurVPass(_c, resolve, graphPass) {
11947
12975
  if (graphPass === void 0) pass.end();
11948
12976
  }
11949
12977
  function recordBloomCompositePass(_c, resolve, graphPass) {
11950
- const { runtime, encoder, camera, tonemapActive, frameState, bindGroupCounts } = _c;
12978
+ const { runtime, encoder, camera, frameState, bindGroupCounts } = _c;
11951
12979
  const pp = _c.bloomResources;
11952
- if (camera.bloom !== "on" || !tonemapActive) return;
12980
+ if (!bloomRecordActive(_c)) return;
11953
12981
  if (pp === null || pp === void 0) {
11954
12982
  throwBloomRecordFailure("Bloom persistent resources are ready before composite encoding");
11955
12983
  }
@@ -11959,10 +12987,11 @@ function recordBloomCompositePass(_c, resolve, graphPass) {
11959
12987
  );
11960
12988
  }
11961
12989
  const hdrColorView = resolve?.resolve("hdrColor");
11962
- const bloomBlurVView = resolve?.resolve("bloomBlurV");
12990
+ const bloomView = resolve?.resolve("bloomUpsample0");
12991
+ const finestBloomView = bloomView ?? resolve?.resolve("bloomDownsample0");
11963
12992
  const hdrCompositedView = resolve?.resolve("hdrComposited");
11964
- if (!hdrColorView || !bloomBlurVView || !hdrCompositedView) {
11965
- throwBloomRecordFailure("Bloom composite pass resolves its source and target views");
12993
+ if (!hdrColorView || !finestBloomView || !hdrCompositedView) {
12994
+ throwBloomRecordFailure("Bloom composite pass resolves scene, finest Bloom, and target views");
11966
12995
  }
11967
12996
  const bglComposite = pp.bloomCompositeBindGroupLayout;
11968
12997
  const bloomSampler = pp.bloomSampler;
@@ -11977,7 +13006,7 @@ function recordBloomCompositePass(_c, resolve, graphPass) {
11977
13006
  stageBloomUpload(_c);
11978
13007
  const bindGroup = getOrCreateFromChain(
11979
13008
  frameState.postProcessBgCache,
11980
- [hdrColorView, bloomBlurVView],
13009
+ [hdrColorView, finestBloomView],
11981
13010
  "bloom-composite",
11982
13011
  () => {
11983
13012
  const bgRes = runtime.device.createBindGroup({
@@ -11985,7 +13014,7 @@ function recordBloomCompositePass(_c, resolve, graphPass) {
11985
13014
  layout: bglComposite,
11986
13015
  entries: [
11987
13016
  { binding: 0, resource: { kind: "textureView", value: hdrColorView } },
11988
- { binding: 1, resource: { kind: "textureView", value: bloomBlurVView } },
13017
+ { binding: 1, resource: { kind: "textureView", value: finestBloomView } },
11989
13018
  { binding: 2, resource: { kind: "sampler", value: bloomSampler } },
11990
13019
  {
11991
13020
  binding: 3,
@@ -12013,7 +13042,7 @@ function recordBloomCompositePass(_c, resolve, graphPass) {
12013
13042
  stageBloomEncode(_c);
12014
13043
  if (graphPass === void 0) pass.end();
12015
13044
  }
12016
- function recordFxaaPass(c, resolve, graphPass, paramsOverride) {
13045
+ function recordFxaaPass(c, resolve, graphPass, paramsOverride, graphOutputFormat) {
12017
13046
  const { runtime, pipelineState, encoder, camera, currentTexture } = c;
12018
13047
  const fxaaActive = camera.antialias === "fxaa";
12019
13048
  if (fxaaActive && pipelineState.perPassResources.fxaaPipeline !== null && pipelineState.perPassResources.fxaaBindGroupLayout !== null && pipelineState.perPassResources.fxaaSampler !== null && runtime.getPostProcessParamsBuffer !== void 0) {
@@ -12060,7 +13089,7 @@ function recordFxaaPass(c, resolve, graphPass, paramsOverride) {
12060
13089
  },
12061
13090
  c.bindGroupCounts
12062
13091
  );
12063
- const fxaaColorFormat = runtime.device.caps.storageBuffer ? pipelineState.format : pipelineState.colorAttachmentFormat;
13092
+ const fxaaColorFormat = graphPass !== void 0 && graphOutputFormat !== void 0 ? graphOutputFormat : runtime.device.caps.storageBuffer ? pipelineState.format : pipelineState.colorAttachmentFormat;
12064
13093
  let fxaaPass = graphPass;
12065
13094
  if (fxaaPass === void 0) {
12066
13095
  const fxaaOutputView = runtime.device.createTextureView(currentTexture, {
@@ -12079,7 +13108,19 @@ function recordFxaaPass(c, resolve, graphPass, paramsOverride) {
12079
13108
  )
12080
13109
  );
12081
13110
  }
12082
- fxaaPass.setPipeline(pipelineState.perPassResources.fxaaPipeline);
13111
+ let fxaaPipeline = pipelineState.perPassResources.fxaaPipeline;
13112
+ if (graphPass !== void 0 && graphOutputFormat !== void 0) {
13113
+ const entry = runtime.lookupPostProcess?.(FXAA_POST_PROCESS_ID);
13114
+ const rebuilt = entry === void 0 || runtime.getPostProcessPipeline === void 0 ? null : runtime.getPostProcessPipeline(
13115
+ FXAA_POST_PROCESS_ID,
13116
+ fxaaBglLayout,
13117
+ [graphOutputFormat],
13118
+ entry
13119
+ );
13120
+ if (rebuilt !== null) fxaaPipeline = rebuilt;
13121
+ }
13122
+ if (fxaaPipeline === null) return;
13123
+ fxaaPass.setPipeline(fxaaPipeline);
12083
13124
  fxaaPass.setBindGroup(0, fxaaBg);
12084
13125
  fxaaPass.draw(3, 1, 0, 0);
12085
13126
  if (graphPass === void 0) fxaaPass.end();
@@ -12110,8 +13151,8 @@ function postProcessSourceDigest(source) {
12110
13151
  function postProcessShaderPipelineLabel(identity, source) {
12111
13152
  return `post-process-${identity}-pso-${postProcessSourceDigest(source)}`;
12112
13153
  }
12113
- function postProcessShaderModuleLabel(identity, source) {
12114
- return `${postProcessShaderPipelineLabel(identity, source)}-module`;
13154
+ function postProcessShaderModuleLabel(source) {
13155
+ return `post-process-module-${postProcessSourceDigest(source)}`;
12115
13156
  }
12116
13157
  function postProcessShaderEntrySignature(entry) {
12117
13158
  return JSON.stringify({
@@ -12121,7 +13162,9 @@ function postProcessShaderEntrySignature(entry) {
12121
13162
  byteSize: entry.params.byteSize,
12122
13163
  defaultValue: Array.from(entry.params.defaultValue)
12123
13164
  },
12124
- reads: entry.reads
13165
+ reads: entry.reads,
13166
+ usesView: entry.usesView,
13167
+ storageBindings: entry.storageBindings
12125
13168
  });
12126
13169
  }
12127
13170
  function isTemporalFullscreenBinding(values) {
@@ -12155,7 +13198,10 @@ var DEPTH_MIN_PARAMS_BYTE_SIZE = 16;
12155
13198
  function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12156
13199
  const { device } = ctx;
12157
13200
  const hasDepth = entryHasDepthRead(entry);
12158
- const bglKind = hasDepth ? depthMultisampled ? "fullscreen-post-with-scene-depth-msaa" : "fullscreen-post-with-scene-depth" : entry.params !== void 0 ? "fullscreen-post-with-params" : "fullscreen-post";
13201
+ const hasMultisampledColor = (entry.reads ?? []).some(
13202
+ (read) => typeof read !== "string" && read.sampleType === "multisampled-float"
13203
+ );
13204
+ const bglKind = hasDepth ? depthMultisampled ? hasMultisampledColor ? "fullscreen-post-with-paired-msaa" : "fullscreen-post-with-scene-depth-msaa" : "fullscreen-post-with-scene-depth" : entry.params !== void 0 ? "fullscreen-post-with-params" : "fullscreen-post";
12159
13205
  const descriptor = buildBindGroupLayoutDescriptor(FULLSCREEN_DEFAULT_SPEC, { kind: bglKind });
12160
13206
  const colorReads = (entry.reads ?? []).filter(
12161
13207
  (read) => typeof read === "string" || read.sampleType !== "depth"
@@ -12169,6 +13215,14 @@ function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12169
13215
  texture: { sampleType: "float", viewDimension: "2d" }
12170
13216
  });
12171
13217
  }
13218
+ const firstStorageBinding = firstExtraBinding + extraColorCount;
13219
+ for (const [index, binding] of (entry.storageBindings ?? []).entries()) {
13220
+ descriptor.entries.push({
13221
+ binding: binding ?? firstStorageBinding + index,
13222
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
13223
+ buffer: { type: "read-only-storage" }
13224
+ });
13225
+ }
12172
13226
  const bglRes = device.createBindGroupLayout(descriptor);
12173
13227
  if (!bglRes.ok) {
12174
13228
  ctx.errorRegistry.fire(bglRes.error);
@@ -12183,6 +13237,9 @@ function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12183
13237
  extraColorBindings: Object.freeze(
12184
13238
  Array.from({ length: extraColorCount }, (_, index) => firstExtraBinding + index)
12185
13239
  ),
13240
+ extraStorageBindings: Object.freeze(
13241
+ (entry.storageBindings ?? []).map((binding, index) => binding ?? firstStorageBinding + index)
13242
+ ),
12186
13243
  createHandle: (name, pipeline, paramsBuffer) => ({
12187
13244
  name,
12188
13245
  paramsBuffer,
@@ -12193,7 +13250,7 @@ function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12193
13250
  })
12194
13251
  };
12195
13252
  }
12196
- function createFullscreenBindGroup(device, bgl, inputView, sampler, paramsBuffer, depthTexView, depthSampler, additionalViews = []) {
13253
+ function createFullscreenBindGroup(device, bgl, inputView, sampler, paramsBuffer, depthTexView, depthSampler, additionalViews = [], additionalBuffers = []) {
12197
13254
  const entries = [
12198
13255
  { binding: 0, resource: { kind: "textureView", value: inputView } }
12199
13256
  ];
@@ -12213,6 +13270,12 @@ function createFullscreenBindGroup(device, bgl, inputView, sampler, paramsBuffer
12213
13270
  resource: { kind: "textureView", value: additional.view }
12214
13271
  });
12215
13272
  }
13273
+ for (const additional of additionalBuffers) {
13274
+ entries.push({
13275
+ binding: additional.binding,
13276
+ resource: { kind: "buffer", value: { buffer: additional.buffer } }
13277
+ });
13278
+ }
12216
13279
  const res = device.createBindGroup({
12217
13280
  label: "fullscreen-post-process-bg",
12218
13281
  layout: bgl,
@@ -12504,7 +13567,13 @@ function dispatchFullscreenPass(ctx, name, shader, color, reads, resolveCtx, com
12504
13567
  detail: { readsKey: reads[0] ?? "ldrColor", passName: name }
12505
13568
  });
12506
13569
  }
12507
- recordFxaaPass(requireRenderGraphRecordContext(ctx), resolveCtx, graphPass, paramsOverride);
13570
+ recordFxaaPass(
13571
+ requireRenderGraphRecordContext(ctx),
13572
+ resolveCtx,
13573
+ graphPass,
13574
+ paramsOverride,
13575
+ graphOutputFormat
13576
+ );
12508
13577
  return;
12509
13578
  }
12510
13579
  const lookup = ctx.runtime.lookupPostProcess;
@@ -12697,6 +13766,11 @@ var TEMPORAL_HISTORY_FORMATS = Object.freeze({
12697
13766
  temporal: "rgba16float",
12698
13767
  stability: "r8unorm"
12699
13768
  });
13769
+ var CLOUD_HISTORY_FORMATS = Object.freeze({
13770
+ radiance: "rgba16float",
13771
+ transmittance: "rgba16float",
13772
+ depth: "rgba16float"
13773
+ });
12700
13774
  function createSurface(device, childScope, label, width, height, format = TEMPORAL_HISTORY_FORMATS.color) {
12701
13775
  const texture = device.createTexture({
12702
13776
  label,
@@ -12720,8 +13794,15 @@ function createSurface(device, childScope, label, width, height, format = TEMPOR
12720
13794
  if (!view.ok) throw view.error;
12721
13795
  return { texture: texture.value, view: view.value };
12722
13796
  }
12723
- function createState(device, scope, width, height) {
13797
+ function cloudHistoryExtent(width, height) {
13798
+ return {
13799
+ width: Math.max(1, Math.ceil(width / 2)),
13800
+ height: Math.max(1, Math.ceil(height / 2))
13801
+ };
13802
+ }
13803
+ function createState(device, scope, width, height, cloudHistoryEnabled) {
12724
13804
  const childScope = scope.createChild(`${scope.owner}:temporal`);
13805
+ const cloudExtent = cloudHistoryExtent(width, height);
12725
13806
  try {
12726
13807
  return {
12727
13808
  device,
@@ -12772,6 +13853,59 @@ function createState(device, scope, width, height) {
12772
13853
  TEMPORAL_HISTORY_FORMATS.stability
12773
13854
  )
12774
13855
  ],
13856
+ cloudHistoryEnabled,
13857
+ cloudRadiance: cloudHistoryEnabled ? [
13858
+ createSurface(
13859
+ device,
13860
+ childScope,
13861
+ "cloud-history-radiance-a",
13862
+ cloudExtent.width,
13863
+ cloudExtent.height
13864
+ ),
13865
+ createSurface(
13866
+ device,
13867
+ childScope,
13868
+ "cloud-history-radiance-b",
13869
+ cloudExtent.width,
13870
+ cloudExtent.height
13871
+ )
13872
+ ] : void 0,
13873
+ cloudTransmittance: cloudHistoryEnabled ? [
13874
+ createSurface(
13875
+ device,
13876
+ childScope,
13877
+ "cloud-history-transmittance-a",
13878
+ cloudExtent.width,
13879
+ cloudExtent.height,
13880
+ CLOUD_HISTORY_FORMATS.transmittance
13881
+ ),
13882
+ createSurface(
13883
+ device,
13884
+ childScope,
13885
+ "cloud-history-transmittance-b",
13886
+ cloudExtent.width,
13887
+ cloudExtent.height,
13888
+ CLOUD_HISTORY_FORMATS.transmittance
13889
+ )
13890
+ ] : void 0,
13891
+ cloudDepth: cloudHistoryEnabled ? [
13892
+ createSurface(
13893
+ device,
13894
+ childScope,
13895
+ "cloud-history-depth-a",
13896
+ cloudExtent.width,
13897
+ cloudExtent.height,
13898
+ CLOUD_HISTORY_FORMATS.depth
13899
+ ),
13900
+ createSurface(
13901
+ device,
13902
+ childScope,
13903
+ "cloud-history-depth-b",
13904
+ cloudExtent.width,
13905
+ cloudExtent.height,
13906
+ CLOUD_HISTORY_FORMATS.depth
13907
+ )
13908
+ ] : void 0,
12775
13909
  bindGroupLayout: void 0,
12776
13910
  sampler: void 0,
12777
13911
  temporalSampler: void 0,
@@ -12806,16 +13940,17 @@ function getTemporalParamsBuffer(state) {
12806
13940
  state.paramsBuffer = created.value;
12807
13941
  return created.value;
12808
13942
  }
12809
- function getTemporalGpuState(frameState, device, scope, width, height) {
13943
+ function getTemporalGpuState(frameState, device, scope, width, height, cloudHistoryRequested = false) {
13944
+ const wantsCloudHistory = cloudHistoryRequested || frameState.pendingCloudHistoryActive === true || frameState.cloudHistoryActive === true;
13945
+ const matches = (state) => state !== void 0 && state.scope === scope && state.width === width && state.height === height && // Cloud history is a demand-shaped part of the temporal allocation. Keep
13946
+ // the two shapes distinct so turning CloudLayer off retires its six HDR
13947
+ // surfaces instead of retaining them on an otherwise TAA-only frame.
13948
+ state.cloudHistoryEnabled === wantsCloudHistory;
12810
13949
  const staged = frameState.temporalGpuState;
12811
- if (staged !== void 0 && staged.scope === scope && staged.width === width && staged.height === height) {
12812
- return staged;
12813
- }
13950
+ if (matches(staged)) return staged;
12814
13951
  const existing = frameState.activeTemporalGpuState;
12815
- if (existing !== void 0 && existing.scope === scope && existing.width === width && existing.height === height) {
12816
- return existing;
12817
- }
12818
- const next = createState(device, scope, width, height);
13952
+ if (matches(existing)) return existing;
13953
+ const next = createState(device, scope, width, height, wantsCloudHistory);
12819
13954
  frameState.temporalGpuState = next;
12820
13955
  return next;
12821
13956
  }
@@ -13099,7 +14234,11 @@ function addTypedScenePass(graph, options) {
13099
14234
  resource: target.view,
13100
14235
  usage: "sampled-read"
13101
14236
  })),
14237
+ ...options.cloudShadow === void 0 ? [] : [{ resource: options.cloudShadow.view, usage: "sampled-read" }],
13102
14238
  ...options.transmissionBackdrop === void 0 ? [] : [{ resource: options.transmissionBackdrop, usage: "sampled-read" }],
14239
+ ...options.surfacePair?.rawDepth.status === "available" ? [{ resource: options.surfacePair.rawDepth.view, usage: "sampled-read" }] : [],
14240
+ ...options.recordMode === "single-layer-medium-color" && options.surfaceNearestLayer !== void 0 ? [{ resource: options.surfaceNearestLayer, usage: "sampled-read" }] : [],
14241
+ ...options.recordMode === "single-layer-medium-color" && options.surfaceNearestDepth !== void 0 ? [{ resource: options.surfaceNearestDepth, usage: "sampled-read" }] : [],
13103
14242
  ...options.environment === void 0 ? [] : [options.environment.irradiance, options.environment.prefilter].map((resource) => ({
13104
14243
  resource,
13105
14244
  usage: "sampled-read"
@@ -13141,8 +14280,12 @@ function addTypedScenePass(graph, options) {
13141
14280
  const internal = frame;
13142
14281
  const directionalShadow = options.directionalShadow === void 0 ? void 0 : resolvedView(resources, options.directionalShadow.view);
13143
14282
  const spotShadow = options.spotShadow === void 0 ? void 0 : resolvedView(resources, options.spotShadow.view);
14283
+ const cloudShadow = options.cloudShadow === void 0 ? void 0 : resolvedView(resources, options.cloudShadow.view);
13144
14284
  const ssao = options.ssao === void 0 ? void 0 : resolvedView(resources, options.ssao.view);
13145
14285
  const transmissionBackdrop = options.transmissionBackdrop === void 0 ? null : resolvedView(resources, options.transmissionBackdrop);
14286
+ const surfaceRawDepth = options.surfacePair?.rawDepth.status === "available" ? resolvedView(resources, options.surfacePair.rawDepth.view) : null;
14287
+ const surfaceNearestLayer = options.surfaceNearestLayer === void 0 ? null : resolvedView(resources, options.surfaceNearestLayer);
14288
+ const surfaceNearestDepth = options.surfaceNearestDepth === void 0 ? null : resolvedView(resources, options.surfaceNearestDepth);
13146
14289
  internal.frameState.currentDirectionalShadowView = directionalShadow ?? null;
13147
14290
  internal.frameState.currentSpotShadowView = spotShadow ?? null;
13148
14291
  const groups = buildPerFrameBindGroups(
@@ -13154,6 +14297,7 @@ function addTypedScenePass(graph, options) {
13154
14297
  {
13155
14298
  directionalShadow,
13156
14299
  spotShadow,
14300
+ cloudShadow,
13157
14301
  projector: internal.spotLightProjector?.view ?? internal.volumetricFog?.projectorView,
13158
14302
  projectorSampler: internal.spotLightProjector?.sampler ?? internal.volumetricFog?.projectorSampler
13159
14303
  },
@@ -13189,11 +14333,17 @@ function addTypedScenePass(graph, options) {
13189
14333
  passKind: options.passKind ?? "forward",
13190
14334
  ...options.clearColor === void 0 ? {} : { clearColor: options.clearColor },
13191
14335
  ...options.recordMode === void 0 ? {} : { recordMode: options.recordMode },
14336
+ ...options.transparentDepthWrite === void 0 ? {} : { transparentDepthWrite: options.transparentDepthWrite },
13192
14337
  ...options.coverageOnly === void 0 ? {} : { coverageOnly: options.coverageOnly },
13193
14338
  ...options.excludeSelector === void 0 ? {} : { excludeSelector: options.excludeSelector },
13194
14339
  ...options.includeSelector === void 0 ? {} : { includeSelector: options.includeSelector },
13195
14340
  ...options.transmissionBackdrop === void 0 ? {} : { transmissionBackdropView: transmissionBackdrop },
13196
- ...options.gpuDriven === void 0 ? {} : { gpuDriven: { projection: options.gpuDriven, resources } }
14341
+ ...surfaceRawDepth === null ? {} : { surfaceRawDepthView: surfaceRawDepth },
14342
+ ...surfaceNearestLayer === null ? {} : { surfaceNearestLayerView: surfaceNearestLayer },
14343
+ ...surfaceNearestDepth === null ? {} : { surfaceNearestDepthView: surfaceNearestDepth },
14344
+ ...options.recordMode === "single-layer-medium-nearest-layer" ? { fragmentEntryPoint: "fs_nearest_layer" } : options.recordMode === "single-layer-medium-color" ? { fragmentEntryPoint: "fs_color" } : {},
14345
+ ...options.gpuDriven === void 0 ? {} : { gpuDriven: { projection: options.gpuDriven, resources } },
14346
+ ...options.gpuDrivenFilter === void 0 ? {} : { gpuDrivenFilter: options.gpuDrivenFilter }
13197
14347
  });
13198
14348
  if (passContext.materialUboPayloadCache !== void 0) {
13199
14349
  internal.materialUboPayloadCache = passContext.materialUboPayloadCache;
@@ -13232,46 +14382,32 @@ function addReflectionFallbackObservationPass(graph, target) {
13232
14382
  });
13233
14383
  }
13234
14384
  var TYPED_BLOOM_PASS_NAMES = {
13235
- bright: "bloom-bright",
13236
- blurH: "bloom-blur-h",
13237
- blurV: "bloom-blur-v",
14385
+ downsample: "bloom-downsample",
14386
+ upsample: "bloom-upsample",
13238
14387
  composite: "bloom-composite"
13239
14388
  };
14389
+ function typedBloomLevelPassName(kind, level) {
14390
+ return `${TYPED_BLOOM_PASS_NAMES[kind]}-${level}`;
14391
+ }
13240
14392
  function addTypedBloomPasses(graph, targets) {
13241
14393
  const named = {
13242
14394
  hdrColor: targets.scene,
13243
- hdrComposited: targets.composited,
13244
- bloomBright: targets.bright,
13245
- bloomBlurH: targets.blurH,
13246
- bloomBlurV: targets.blurV
14395
+ hdrComposited: targets.composited
13247
14396
  };
13248
- const descriptors = [
13249
- {
13250
- name: TYPED_BLOOM_PASS_NAMES.bright,
13251
- reads: [targets.scene],
13252
- write: targets.bright,
13253
- encode: recordBloomBrightPass
13254
- },
13255
- {
13256
- name: TYPED_BLOOM_PASS_NAMES.blurH,
13257
- reads: [targets.bright],
13258
- write: targets.blurH,
13259
- encode: recordBloomBlurHPass
13260
- },
13261
- {
13262
- name: TYPED_BLOOM_PASS_NAMES.blurV,
13263
- reads: [targets.blurH],
13264
- write: targets.blurV,
13265
- encode: recordBloomBlurVPass
13266
- },
13267
- {
13268
- name: TYPED_BLOOM_PASS_NAMES.composite,
13269
- reads: [targets.scene, targets.blurV],
13270
- write: targets.composited,
13271
- encode: recordBloomCompositePass
13272
- }
13273
- ];
13274
- for (const descriptor of descriptors) {
14397
+ targets.downsample.forEach((target, level) => {
14398
+ named[`bloomDownsample${level}`] = target;
14399
+ });
14400
+ targets.upsample.forEach((target, level) => {
14401
+ named[`bloomUpsample${level}`] = target;
14402
+ });
14403
+ const add = (name, reads, write, encode, level) => {
14404
+ const descriptor = {
14405
+ name,
14406
+ reads,
14407
+ write,
14408
+ encode,
14409
+ level
14410
+ };
13275
14411
  const added = graph.addRasterPass(descriptor.name, {
13276
14412
  accesses: [
13277
14413
  ...descriptor.reads.map((target) => ({
@@ -13291,12 +14427,80 @@ function addTypedBloomPasses(graph, targets) {
13291
14427
  encode: ({ pass, frame, resources }) => descriptor.encode(
13292
14428
  frame,
13293
14429
  legacyResolver(resources, named),
13294
- pass
14430
+ pass,
14431
+ descriptor.level,
14432
+ descriptor.level === void 0 ? void 0 : targets.levelDimensions[descriptor.level]
13295
14433
  )
13296
14434
  });
14435
+ return added.ok ? ok(void 0) : added;
14436
+ };
14437
+ for (const [level, write] of targets.downsample.entries()) {
14438
+ const source = level === 0 ? targets.scene : targets.downsample[level - 1];
14439
+ if (source === void 0) {
14440
+ return err$1(
14441
+ new RenderGraphError({
14442
+ code: "resource-resolution-failed",
14443
+ expected: "Bloom downsample levels form one adjacent pyramid",
14444
+ hint: "rebuild the Standard Bloom target declaration from one level list",
14445
+ detail: { resourceLabel: `bloom-level-${level}` }
14446
+ })
14447
+ );
14448
+ }
14449
+ const added = add(
14450
+ typedBloomLevelPassName("downsample", level),
14451
+ [source],
14452
+ write,
14453
+ (frame, resolve, pass, passLevel) => recordBloomDownsamplePass(
14454
+ frame,
14455
+ resolve,
14456
+ pass,
14457
+ passLevel ?? level,
14458
+ targets.levelDimensions[passLevel ?? level]
14459
+ ),
14460
+ level
14461
+ );
13297
14462
  if (!added.ok) return added;
13298
14463
  }
13299
- return ok(void 0);
14464
+ for (let level = targets.upsample.length - 1; level >= 0; level -= 1) {
14465
+ const current = targets.downsample[level];
14466
+ const coarse = level === targets.downsample.length - 2 ? targets.downsample[level + 1] : targets.upsample[level + 1];
14467
+ const write = targets.upsample[level];
14468
+ if (current === void 0 || coarse === void 0 || write === void 0) {
14469
+ return err$1(
14470
+ new RenderGraphError({
14471
+ code: "resource-resolution-failed",
14472
+ expected: "Bloom downsample and upsample levels form one adjacent pyramid",
14473
+ hint: "rebuild the Standard Bloom target declaration from one level list",
14474
+ detail: { resourceLabel: `bloom-level-${level}` }
14475
+ })
14476
+ );
14477
+ }
14478
+ const added = add(
14479
+ typedBloomLevelPassName("upsample", level),
14480
+ [current, coarse],
14481
+ write,
14482
+ (frame, resolve, pass, passLevel) => recordBloomUpsamplePass(frame, resolve, pass, passLevel ?? level),
14483
+ level
14484
+ );
14485
+ if (!added.ok) return added;
14486
+ }
14487
+ const finest = targets.upsample[0] ?? targets.downsample[0];
14488
+ if (finest === void 0) {
14489
+ return err$1(
14490
+ new RenderGraphError({
14491
+ code: "resource-resolution-failed",
14492
+ expected: "Bloom has at least one downsample level",
14493
+ hint: "derive Bloom levels from a positive output extent",
14494
+ detail: { resourceLabel: "bloom-downsample-0" }
14495
+ })
14496
+ );
14497
+ }
14498
+ return add(
14499
+ TYPED_BLOOM_PASS_NAMES.composite,
14500
+ [targets.scene, finest],
14501
+ targets.composited,
14502
+ (frame, resolve, pass) => recordBloomCompositePass(frame, resolve, pass)
14503
+ );
13300
14504
  }
13301
14505
  function addTypedSsaoPasses(graph, targets) {
13302
14506
  const calc = graph.addRasterPass("ssao-calc", {
@@ -13682,6 +14886,11 @@ function addStandardSceneDataPass(graph, target, depth) {
13682
14886
  color: target,
13683
14887
  depth,
13684
14888
  selector: { LightMode: ["Deferred", "Forward"] },
14889
+ // The temporal producer runs before the Surface raw-depth/nearest-layer
14890
+ // pair. Keep it on the ordinary opaque Standard lane rather than asking
14891
+ // a medium material to assemble a bind group from resources that this
14892
+ // pass cannot own yet.
14893
+ recordMode: "opaque",
13685
14894
  passKind: "temporal",
13686
14895
  // The temporal producer re-rasterizes the current scene after the main
13687
14896
  // color pass has populated depth. Its output is a semantic motion target;
@@ -13707,6 +14916,6 @@ function addTaaResolvePass(graph, current, currentTemporal, previousColor, previ
13707
14916
  });
13708
14917
  }
13709
14918
 
13710
- export { BYTES_PER_DIRECT_LIGHT_SLOT, BatchTopology, CAPTURE_VIEW_PROJS, CUBEMAP_FACE_VERTICES, CUBE_CAPTURE_VIEW_SLOT_BASE, DEFERRED_COLOR_FORMATS, DEPTH_MIN_PARAMS_BYTE_SIZE, FALLBACK_BYTES_PER_ROW, GPU_DRIVEN_VIEW_WGSL, GPU_SCENE_LAYOUTS, GpuBuffer, GpuDrivenView, GpuTexture, MATERIAL_PER_ENTITY_STRIDE, MESH_SSBO_BYTES, OcclusionConfidenceScheduler, POINTS_LINES_MATERIAL_SHADER_ID, POINTS_LINES_VIEW_BUFFER_SIZE, PREFILTER_MIP_LEVELS, PREFILTER_SIZE, PipelineSpecError, PostProcessError, REFLECTION_PROBE_VIEW_SLOT_BASE, SHADOW_CASTER_BUFFER_SIZE, STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES, STANDARD_PBR_UBO_SIZE, ShadowViewStatePool, TEMPORAL_HISTORY_FORMATS, TYPED_BLOOM_PASS_NAMES, VIEW_UNIFORM_BUFFER_SIZE, VIEW_UNIFORM_BYTES, VIEW_UNIFORM_SLOT_STRIDE, abortTemporalGpuSubmit, addReflectionFallbackObservationPass, addStandardSceneDataPass, addTaaResolvePass, addTypedBloomPasses, addTypedCompositePostEffects, addTypedFrameObservationPass, addTypedFullscreenPass, addTypedOutputTransformPass, addTypedScenePass, addTypedSkyboxPass, addTypedSsaoPasses, addTypedTemporalResolvePass, aggregateTemporalDemand, applyMaterialTextureUvScales, applyParamSchemaDefaultsToUbo, applyParamSnapshotToUbo, assembleMaterialWithSkylightEntries, assertStorageBufferCap, buildFoldDispatchPlan, buildFullscreenPostProcessPass, buildLinearLdrMaterialSpecTable, buildPerFrameBindGroups, buildSpecConstTable, cacheKeyOf, cleanPerEntityCache, colorFormatsForPassKind, commitTemporalGpuSubmit, computeProjectionMatrix, computeSplitLdrSprite, computeViewMatrix, configureSurface, createClusterBinScratch, createFullscreenBindGroup, createHdrpClusterMembershipBindGroupLayoutDescriptor, createIblPipelines, createPointsLinesLaneAdapter, createPointsLinesLaneContract, createRenderPipelineTarget, createSkylightFallback, createStandardSceneDataTarget, createStandardSurfaceLightingBindGroup, decideVisibility, defaultViewForUserRegionField, deriveRenderDataCubemap, deriveRenderDataMesh, deriveRenderDataTexture, deriveRenderExtent, describeTemporalDemand, detectNineSliceScaleTooSmall, deviceOptionsForAdapter, driveLazyEquirectProjection, encodeDirectionalShadowPass, encodeMainPass, encodePointShadowPass, encodeSpotShadowPass, ensureMeshSsboCapacity, entryHasDepthRead, evaluateFoldBucketUniformCap, foldDispatchBuckets, geometryRenderStateForPass, geometryRenderStateForTopology, getIblProbeBackgroundSource, getOrBuildPipeline, getOrCreateFromChain, getOrCreateHdrpBuffers, getOrCreateIblCache, getTemporalBindGroupResources, getTemporalGpuState, getTemporalParamsBuffer, gpuSceneFieldOffset, hasPendingTemporalGpuSubmit, importRenderPipelineSurface, incrementFoldedDrawsMetric, isTemporalFullscreenBinding, packInstanceStorageBuffer, passKindPolicyTable, postProcessShaderEntrySignature, postProcessShaderModuleLabel, postProcessShaderPipelineLabel, prepareFrameLighting, prepareMaterialSkylight, prewarmMaterialShaderVariants, projectedHeightForCandidate, renderExtentSize, resetHdrpBuffers, residentTextureView, resolveMaterialSkylight, resolveOutputDither, resolveReflectionProbeBinding, resolveSkyboxActive, resolveSsaoParameters, resolveSurfaceFormatPair, resolveSurfaceProfile, retireTemporalGpuState, retireTemporalGpuStateAfterFence, runIblPrecompute, selectGpuDrivenSceneIndexVariant, selectGpuLodLane, selectHdrpPbrPrewarmVariants, selectLazyEquirectHandle, selectLod, selectProbePrewarmVariants, selectSkinPrewarmVariants, selectStandardPbrTransmissionPrewarmVariants, selectSwapChainFormat, setIblComposedShaders, shadowViewIdentityKey, shadowViewRasterAccesses, shouldIssueRetest, standardStorageVariantSet, standardTemporalLaneAdmission, standardTemporalPostOrder, standardTopologyVariantSet, temporalReadIndex, temporalWriteIndex, transmissionBackdropAvailable, uploadMeshSsboBatch, variantSetFromDefines, variantSetFromVertexLayoutProjection, warnMultiSkybox, warnMultiSkylight, warnZeroLightStandard, writeHdrpClusterAndSsaoBuffers, writePbrMaterialUboPayload, writePointsLinesViewUbo, writeShadowCasterUniforms, writeShadowParamsBuffer, writeSpotModifierTextures, writeViewUbo };
13711
- //# sourceMappingURL=chunk-JRIPCMYC.mjs.map
13712
- //# sourceMappingURL=chunk-JRIPCMYC.mjs.map
14919
+ export { BLOOM_COMPOSITE_PARAMS_BYTES, BLOOM_DOWNSAMPLE_PARAMS_BYTES, BLOOM_UPSAMPLE_PARAMS_BYTES, BYTES_PER_DIRECT_LIGHT_SLOT, BatchTopology, CAPTURE_VIEW_PROJS, CLOUD_HISTORY_FORMATS, CUBEMAP_FACE_VERTICES, CUBE_CAPTURE_VIEW_SLOT_BASE, DEFERRED_COLOR_FORMATS, DEPTH_MIN_PARAMS_BYTE_SIZE, DEPTH_TEXTURE_FORMAT, FALLBACK_BYTES_PER_ROW, GPU_DRIVEN_VIEW_WGSL, GPU_SCENE_LAYOUTS, GpuBuffer, GpuDrivenView, GpuResourceAllocationLedger, GpuTexture, HDR_COLOR_ATTACHMENT_FORMAT, MATERIAL_PER_ENTITY_STRIDE, MESH_PER_ENTITY_STRIDE, MESH_SSBO_BYTES, MIPMAP_PREWARM_FORMATS, OcclusionConfidenceScheduler, POINTS_LINES_MATERIAL_SHADER_ID, POINTS_LINES_VIEW_BUFFER_SIZE, PREFILTER_MIP_LEVELS, PREFILTER_SIZE, PipelineSpecError, PostProcessError, REFLECTION_PROBE_VIEW_SLOT_BASE, SHADOW_CASTER_BUFFER_SIZE, STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES, STANDARD_PBR_UBO_SIZE, ShadowViewStatePool, SurfaceSubmissionObservationOwner, TEMPORAL_HISTORY_FORMATS, TYPED_BLOOM_PASS_NAMES, VIEW_UBO_BYTES, VIEW_UNIFORM_BYTES, VIEW_UNIFORM_SLOT_STRIDE, abortTemporalGpuSubmit, addReflectionFallbackObservationPass, addStandardSceneDataPass, addTaaResolvePass, addTypedBloomPasses, addTypedCompositePostEffects, addTypedFrameObservationPass, addTypedFullscreenPass, addTypedOutputTransformPass, addTypedScenePass, addTypedSkyboxPass, addTypedSsaoPasses, addTypedTemporalResolvePass, aggregateTemporalDemand, applyMaterialTextureUvScales, applyParamSchemaDefaultsToUbo, applyParamSnapshotToUbo, assembleMaterialWithSkylightEntries, assertStorageBufferCap, buildFoldDispatchPlan, buildFullscreenPostProcessPass, buildLinearLdrMaterialSpecTable, buildPerFrameBindGroups, buildSpecConstTable, cacheKeyOf, cleanPerEntityCache, colorFormatsForPassKind, combineGpuResourceAllocationInspections, commitTemporalGpuSubmit, computeProjectionMatrix, computeSplitLdrSprite, computeViewMatrix, configureSurface, createClusterBinScratch, createFullscreenBindGroup, createHdrpClusterMembershipBindGroupLayoutDescriptor, createIblPipelines, createPointsLinesLaneAdapter, createPointsLinesLaneContract, createRenderPipelineTarget, createSkylightFallback, createStandardSceneDataTarget, createStandardSurfaceLightingBindGroup, decideVisibility, defaultViewForUserRegionField, deriveRenderDataCubemap, deriveRenderDataMesh, deriveRenderDataTexture, deriveRenderExtent, describeTemporalDemand, detectNineSliceScaleTooSmall, deviceOptionsForAdapter, driveLazyEquirectProjection, encodeDirectionalShadowPass, encodeMainPass, encodePointShadowPass, encodeSpotShadowPass, ensureMeshSsboCapacity, ensureProbeBlendRecordBuffer, entryHasDepthRead, evaluateFoldBucketUniformCap, foldDispatchBuckets, geometryRenderStateForPass, geometryRenderStateForTopology, getIblProbeBackgroundSource, getOrBuildPipeline, getOrCreateFromChain, getOrCreateHdrpBuffers, getOrCreateIblCache, getTemporalBindGroupResources, getTemporalGpuState, getTemporalParamsBuffer, gpuSceneFieldOffset, hasPendingTemporalGpuSubmit, importRenderPipelineSurface, incrementFoldedDrawsMetric, inspectResourceClassSplits, isTemporalFullscreenBinding, packInstanceStorageBuffer, passKindPolicyTable, postProcessShaderEntrySignature, postProcessShaderModuleLabel, postProcessShaderPipelineLabel, prepareFrameLighting, prepareMaterialSkylight, prewarmMaterialShaderVariants, projectedHeightForCandidate, renderExtentSize, renderPipelineCloudHistoryTargets, resetHdrpBuffers, resetSsaoResources, residentTextureView, resolveGeometryInstanceBuffer, resolveMaterialSkylight, resolveOutputDither, resolveReflectionProbeBinding, resolveSkyboxActive, resolveSsaoParameters, resolveSurfaceFormatPair, resolveSurfaceProfile, retireTemporalGpuState, retireTemporalGpuStateAfterFence, runIblPrecompute, selectGpuDrivenSceneIndexVariant, selectGpuLodLane, selectHdrpPbrPrewarmVariants, selectLazyEquirectHandle, selectLod, selectProbePrewarmVariants, selectSkinPrewarmVariants, selectStandardPbrTransmissionPrewarmVariants, selectSwapChainFormat, setIblComposedShaders, shadowViewIdentityKey, shadowViewRasterAccesses, shouldIssueRetest, stageTemporalGpuSubmit, standardBloomAdmitted, standardStorageVariantSet, standardTemporalLaneAdmission, standardTemporalPostOrder, standardTopologyVariantSet, temporalReadIndex, temporalWriteIndex, transmissionBackdropAvailable, uploadMeshSsboBatch, variantSetFromDefines, variantSetFromVertexLayoutProjection, warnMultiSkybox, warnMultiSkylight, warnZeroLightStandard, writeHdrpClusterAndSsaoBuffers, writePbrMaterialUboPayload, writePointsLinesViewUbo, writeShadowCasterUniforms, writeShadowParamsBuffer, writeSpotModifierTextures, writeViewUbo };
14920
+ //# sourceMappingURL=chunk-MKDIT2EM.mjs.map
14921
+ //# sourceMappingURL=chunk-MKDIT2EM.mjs.map