@forgeax/engine-render 0.1.33 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (518) hide show
  1. package/README.md +1010 -124
  2. package/dist/assembly/backend-contract.d.ts +2 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  5. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  6. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  7. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  8. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  9. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  10. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  11. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  12. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  14. package/dist/assembly/factory.d.ts +1 -1
  15. package/dist/assembly/factory.d.ts.map +1 -1
  16. package/dist/assembly/host-contract.d.ts +3 -3
  17. package/dist/assembly/host-contract.d.ts.map +1 -1
  18. package/dist/assembly/material/assembly.d.ts.map +1 -1
  19. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  20. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  21. package/dist/assembly/material-shader-policy.d.ts +16 -2
  22. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  23. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  24. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  25. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  26. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  27. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  28. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  29. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  30. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  31. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  32. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  33. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  34. package/dist/assembly/renderer-inspection.d.ts +11 -0
  35. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  36. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  37. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  38. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  39. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  40. package/dist/assembly/webgpu-ready.d.ts +1 -1
  41. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  42. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  43. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  44. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  45. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  46. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  47. package/dist/authoring.mjs +1 -1
  48. package/dist/barrel-distortion.d.ts +47 -0
  49. package/dist/barrel-distortion.d.ts.map +1 -0
  50. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  51. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  52. package/dist/{chunk-ZDQWGQW7.mjs → chunk-HEB564WF.mjs} +4 -4
  53. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-HEB564WF.mjs.map} +1 -1
  54. package/dist/{chunk-VOZWDM3L.mjs → chunk-MKDIT2EM.mjs} +1307 -188
  55. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  56. package/dist/{chunk-LEAXOMYJ.mjs → chunk-OCDLEI6I.mjs} +3 -3
  57. package/dist/{chunk-LEAXOMYJ.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  58. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  59. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  60. package/dist/{chunk-3RTCJTH4.mjs → chunk-SHFUFJ5N.mjs} +184 -13
  61. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  62. package/dist/{chunk-OO3DRYK7.mjs → chunk-UI5SFODX.mjs} +176 -96
  63. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  64. package/dist/{chunk-PLAXOOX5.mjs → chunk-UINHLCZA.mjs} +561 -79
  65. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  66. package/dist/{chunk-NB2S7ZRX.mjs → chunk-WEX45HKH.mjs} +127 -386
  67. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  68. package/dist/cloud/density.d.ts +55 -0
  69. package/dist/cloud/density.d.ts.map +1 -0
  70. package/dist/cloud/extract.d.ts +25 -0
  71. package/dist/cloud/extract.d.ts.map +1 -0
  72. package/dist/cloud/feature.d.ts +57 -0
  73. package/dist/cloud/feature.d.ts.map +1 -0
  74. package/dist/cloud/frame-context.d.ts +8 -0
  75. package/dist/cloud/frame-context.d.ts.map +1 -0
  76. package/dist/cloud/inspection.d.ts +59 -0
  77. package/dist/cloud/inspection.d.ts.map +1 -0
  78. package/dist/cloud/optics.d.ts +56 -0
  79. package/dist/cloud/optics.d.ts.map +1 -0
  80. package/dist/cloud/parameters.d.ts +73 -0
  81. package/dist/cloud/parameters.d.ts.map +1 -0
  82. package/dist/cloud/resources.d.ts +60 -0
  83. package/dist/cloud/resources.d.ts.map +1 -0
  84. package/dist/cloud/shadow.d.ts +42 -0
  85. package/dist/cloud/shadow.d.ts.map +1 -0
  86. package/dist/cloud/temporal.d.ts +74 -0
  87. package/dist/cloud/temporal.d.ts.map +1 -0
  88. package/dist/components/barrel-distortion.d.ts +13 -0
  89. package/dist/components/barrel-distortion.d.ts.map +1 -0
  90. package/dist/components/cloud-layer.d.ts +29 -0
  91. package/dist/components/cloud-layer.d.ts.map +1 -0
  92. package/dist/components/index.d.ts +2 -0
  93. package/dist/components/index.d.ts.map +1 -1
  94. package/dist/components/instances.d.ts +20 -6
  95. package/dist/components/instances.d.ts.map +1 -1
  96. package/dist/construct-renderer.d.ts +1 -1
  97. package/dist/construct-renderer.d.ts.map +1 -1
  98. package/dist/construct-renderer.mjs +6759 -2875
  99. package/dist/construct-renderer.mjs.map +1 -1
  100. package/dist/dynamic-geometry.d.ts +5 -1
  101. package/dist/dynamic-geometry.d.ts.map +1 -1
  102. package/dist/errors/cloud.d.ts +59 -0
  103. package/dist/errors/cloud.d.ts.map +1 -0
  104. package/dist/errors/render.d.ts +18 -4
  105. package/dist/errors/render.d.ts.map +1 -1
  106. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  107. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  108. package/dist/extract/camera.d.ts.map +1 -1
  109. package/dist/extract/contracts.d.ts +5 -1
  110. package/dist/extract/contracts.d.ts.map +1 -1
  111. package/dist/features/barrel-distortion.d.ts +29 -0
  112. package/dist/features/barrel-distortion.d.ts.map +1 -0
  113. package/dist/features/error-reporting.d.ts +6 -2
  114. package/dist/features/error-reporting.d.ts.map +1 -1
  115. package/dist/features/host.d.ts +10 -0
  116. package/dist/features/host.d.ts.map +1 -1
  117. package/dist/features/plan.d.ts +8 -0
  118. package/dist/features/plan.d.ts.map +1 -1
  119. package/dist/features/render-graph-contribution.d.ts +5 -0
  120. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  121. package/dist/features/render-graph-raster.d.ts +1 -0
  122. package/dist/features/render-graph-raster.d.ts.map +1 -1
  123. package/dist/features/targets.d.ts +2 -0
  124. package/dist/features/targets.d.ts.map +1 -1
  125. package/dist/features/types.d.ts +44 -0
  126. package/dist/features/types.d.ts.map +1 -1
  127. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  128. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  129. package/dist/gpu-dirty-ranges.d.ts +11 -0
  130. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  131. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  132. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  133. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  134. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  135. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  136. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  137. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  138. package/dist/gpu-driven/production-raster.d.ts +47 -3
  139. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  140. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  141. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  142. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  143. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  144. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  145. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  146. package/dist/gpu-scene.d.ts +5 -0
  147. package/dist/gpu-scene.d.ts.map +1 -1
  148. package/dist/hdrp-buffers.d.ts +2 -2
  149. package/dist/hdrp-buffers.d.ts.map +1 -1
  150. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  151. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  152. package/dist/index.d.ts +27 -7
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.mjs +258 -8
  155. package/dist/index.mjs.map +1 -1
  156. package/dist/inspection-types.d.ts +135 -1
  157. package/dist/inspection-types.d.ts.map +1 -1
  158. package/dist/instance-buffer-cache.d.ts +4 -4
  159. package/dist/instance-buffer-cache.d.ts.map +1 -1
  160. package/dist/instances.d.ts +48 -100
  161. package/dist/instances.d.ts.map +1 -1
  162. package/dist/internal.mjs +7 -7
  163. package/dist/pbr-pipeline.d.ts +19 -1
  164. package/dist/pbr-pipeline.d.ts.map +1 -1
  165. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  166. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  167. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  168. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  169. package/dist/pipeline/standard-output/types.d.ts +4 -2
  170. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  171. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  172. package/dist/pipeline/standard-post.d.ts.map +1 -1
  173. package/dist/pipeline-builder.d.ts +1 -1
  174. package/dist/pipeline-builder.d.ts.map +1 -1
  175. package/dist/plugin.d.ts.map +1 -1
  176. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  177. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  178. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  179. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  180. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  181. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  182. package/dist/record/fold-buckets.d.ts +95 -0
  183. package/dist/record/fold-buckets.d.ts.map +1 -0
  184. package/dist/record/fold-instance-buffer.d.ts +6 -0
  185. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  186. package/dist/record/frame-lighting.d.ts +1 -0
  187. package/dist/record/frame-lighting.d.ts.map +1 -1
  188. package/dist/record/frame-snapshot.d.ts +37 -3
  189. package/dist/record/frame-snapshot.d.ts.map +1 -1
  190. package/dist/record/frame.d.ts +10 -61
  191. package/dist/record/frame.d.ts.map +1 -1
  192. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  193. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  194. package/dist/record/gpu-timing.d.ts +8 -0
  195. package/dist/record/gpu-timing.d.ts.map +1 -1
  196. package/dist/record/main-pass-geometry.d.ts +21 -5
  197. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  198. package/dist/record/main-pass-material.d.ts +7 -1
  199. package/dist/record/main-pass-material.d.ts.map +1 -1
  200. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  201. package/dist/record/main-pass.d.ts +13 -2
  202. package/dist/record/main-pass.d.ts.map +1 -1
  203. package/dist/record/motion-blur-receipt.d.ts +11 -0
  204. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  205. package/dist/record/probe-blend-buffer.d.ts +16 -0
  206. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  207. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  208. package/dist/record/render-context.d.ts +22 -3
  209. package/dist/record/render-context.d.ts.map +1 -1
  210. package/dist/record/shadow-pass.d.ts +2 -0
  211. package/dist/record/shadow-pass.d.ts.map +1 -1
  212. package/dist/record/skybox-post-pass.d.ts +1 -1
  213. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  214. package/dist/record/typed-frame-graph.d.ts +22 -2
  215. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  216. package/dist/record/view-ubo.d.ts +11 -3
  217. package/dist/record/view-ubo.d.ts.map +1 -1
  218. package/dist/record/volume-params.d.ts +9 -0
  219. package/dist/record/volume-params.d.ts.map +1 -0
  220. package/dist/recovery/render-system-candidate.d.ts +10 -0
  221. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  222. package/dist/reflection/record-owner.d.ts.map +1 -1
  223. package/dist/render-contract.d.ts +42 -4
  224. package/dist/render-contract.d.ts.map +1 -1
  225. package/dist/render-graph-primitives.d.ts.map +1 -1
  226. package/dist/render-pipeline.d.ts +103 -2
  227. package/dist/render-pipeline.d.ts.map +1 -1
  228. package/dist/render-system-extract-tail.d.ts +3 -2
  229. package/dist/render-system-extract-tail.d.ts.map +1 -1
  230. package/dist/render-system-extract.d.ts +16 -9
  231. package/dist/render-system-extract.d.ts.map +1 -1
  232. package/dist/render-system-presentation.d.ts +23 -0
  233. package/dist/render-system-presentation.d.ts.map +1 -0
  234. package/dist/render-system-producer-roots.d.ts +10 -0
  235. package/dist/render-system-producer-roots.d.ts.map +1 -0
  236. package/dist/render-system-residency.d.ts +12 -0
  237. package/dist/render-system-residency.d.ts.map +1 -0
  238. package/dist/render-system.d.ts +19 -14
  239. package/dist/render-system.d.ts.map +1 -1
  240. package/dist/scene/probe-blend.d.ts +27 -0
  241. package/dist/scene/probe-blend.d.ts.map +1 -1
  242. package/dist/scene/render-scene.d.ts +12 -5
  243. package/dist/scene/render-scene.d.ts.map +1 -1
  244. package/dist/ssao-buffers.d.ts +9 -0
  245. package/dist/ssao-buffers.d.ts.map +1 -1
  246. package/dist/surface/dynamic-input.d.ts +133 -0
  247. package/dist/surface/dynamic-input.d.ts.map +1 -0
  248. package/dist/surface/gpu-driven.d.ts +41 -0
  249. package/dist/surface/gpu-driven.d.ts.map +1 -0
  250. package/dist/surface/submission-observation.d.ts +136 -0
  251. package/dist/surface/submission-observation.d.ts.map +1 -0
  252. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  253. package/dist/temporal/gpu.d.ts +13 -1
  254. package/dist/temporal/gpu.d.ts.map +1 -1
  255. package/dist/temporal/index.mjs +5 -5
  256. package/dist/temporal/inspection.d.ts.map +1 -1
  257. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  258. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  259. package/dist/transmission/single-layer-medium.d.ts +89 -0
  260. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  261. package/dist/typed-render-graph-primitives.d.ts +14 -2
  262. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  263. package/dist/volume/component.d.ts +9 -4
  264. package/dist/volume/component.d.ts.map +1 -1
  265. package/dist/volume/extract.d.ts +1 -1
  266. package/dist/volume/extract.d.ts.map +1 -1
  267. package/dist/volume/inspection.d.ts +2 -0
  268. package/dist/volume/inspection.d.ts.map +1 -1
  269. package/dist/volume/passes.d.ts +4 -1
  270. package/dist/volume/passes.d.ts.map +1 -1
  271. package/dist/volume/resources.d.ts.map +1 -1
  272. package/package.json +22 -21
  273. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  274. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  275. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  276. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  277. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  278. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  279. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  280. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  281. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  282. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  283. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  284. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  285. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  286. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  287. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  288. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  289. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  290. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  291. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  292. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  293. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  294. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  295. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  296. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  297. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  298. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  299. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  300. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  301. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  302. package/src/__tests__/instances-store.unit.test.ts +97 -305
  303. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  304. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  305. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  306. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  307. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  308. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  309. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  310. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  311. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  312. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  313. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  314. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  315. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  316. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  317. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  318. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  319. package/src/__tests__/render-error-code-owner.test-d.ts +7 -0
  320. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  321. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  322. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  323. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  324. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  325. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  326. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  327. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  328. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  329. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  330. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  331. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  332. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  333. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  334. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  335. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  336. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  337. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  338. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  339. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  340. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  341. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  342. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  343. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  344. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  345. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  346. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  347. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  348. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  349. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  350. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  351. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  352. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  353. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  354. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  355. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  356. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  357. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  358. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  359. package/src/assembly/backend-contract.ts +30 -0
  360. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  361. package/src/assembly/canvas-draw-guard.ts +11 -0
  362. package/src/assembly/cloud-shadow-entry.ts +22 -0
  363. package/src/assembly/dynamic-geometry-host.ts +65 -37
  364. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  365. package/src/assembly/factory.ts +2 -30
  366. package/src/assembly/host-contract.ts +3 -3
  367. package/src/assembly/material/assembly.ts +25 -13
  368. package/src/assembly/material/pipeline-helpers.ts +53 -12
  369. package/src/assembly/material-shader-policy.ts +55 -0
  370. package/src/assembly/material-shader-prewarm.ts +21 -10
  371. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  372. package/src/assembly/recovery/renderer-recover.ts +41 -18
  373. package/src/assembly/render-feature-post-processes.ts +54 -0
  374. package/src/assembly/renderer-facade.ts +4 -1
  375. package/src/assembly/renderer-feature-inspection.ts +8 -2
  376. package/src/assembly/renderer-frame-transaction.ts +23 -0
  377. package/src/assembly/renderer-inspection.ts +28 -0
  378. package/src/assembly/skin-palette-owner.ts +1 -1
  379. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  380. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  381. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  382. package/src/assembly/webgpu-ready.ts +115 -61
  383. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  384. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  385. package/src/assembly/webgpu-renderer.ts +214 -252
  386. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  387. package/src/barrel-distortion.ts +247 -0
  388. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  389. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  390. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  391. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  392. package/src/cloud/density.ts +600 -0
  393. package/src/cloud/extract.ts +110 -0
  394. package/src/cloud/feature.ts +1810 -0
  395. package/src/cloud/frame-context.ts +42 -0
  396. package/src/cloud/inspection.ts +130 -0
  397. package/src/cloud/optics.ts +285 -0
  398. package/src/cloud/parameters.ts +255 -0
  399. package/src/cloud/resources.ts +122 -0
  400. package/src/cloud/shadow.ts +167 -0
  401. package/src/cloud/temporal.ts +226 -0
  402. package/src/components/barrel-distortion.ts +46 -0
  403. package/src/components/cloud-layer.ts +47 -0
  404. package/src/components/index.ts +2 -0
  405. package/src/components/instances.ts +18 -45
  406. package/src/components/sprite-instances.ts +1 -1
  407. package/src/construct-renderer.ts +1 -1
  408. package/src/dynamic-geometry.ts +12 -1
  409. package/src/errors/cloud.ts +103 -0
  410. package/src/errors/render.ts +44 -7
  411. package/src/examples/single-layer-medium-surface.ts +59 -0
  412. package/src/extract/camera.ts +15 -1
  413. package/src/extract/contracts.ts +5 -0
  414. package/src/features/barrel-distortion.ts +172 -0
  415. package/src/features/error-reporting.ts +26 -6
  416. package/src/features/host.ts +115 -14
  417. package/src/features/plan.ts +8 -0
  418. package/src/features/render-graph-contribution.ts +9 -0
  419. package/src/features/render-graph-raster.ts +45 -3
  420. package/src/features/targets.ts +66 -0
  421. package/src/features/types.ts +47 -0
  422. package/src/fullscreen-post-process-pass.ts +41 -9
  423. package/src/gpu-dirty-ranges.ts +48 -0
  424. package/src/gpu-driven/batch-topology.ts +53 -0
  425. package/src/gpu-driven/material-artifacts.ts +33 -25
  426. package/src/gpu-driven/prepared-draw.ts +12 -4
  427. package/src/gpu-driven/production-raster-material.ts +1894 -0
  428. package/src/gpu-driven/production-raster.ts +825 -784
  429. package/src/gpu-driven/resource-allocation.ts +142 -0
  430. package/src/gpu-driven/shadow-ownership.ts +71 -0
  431. package/src/gpu-driven/view-gpu.ts +164 -10
  432. package/src/gpu-scene.ts +75 -84
  433. package/src/hdrp-buffers.ts +4 -3
  434. package/src/ibl/skylight-bind-group.ts +49 -7
  435. package/src/index.ts +196 -9
  436. package/src/inspection-types.ts +162 -0
  437. package/src/instance-buffer-cache.ts +4 -4
  438. package/src/instances.ts +149 -569
  439. package/src/pbr-pipeline.ts +219 -13
  440. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  441. package/src/pipeline/standard-forward-lane.ts +313 -57
  442. package/src/pipeline/standard-output/graph.ts +8 -2
  443. package/src/pipeline/standard-output/types.ts +12 -1
  444. package/src/pipeline/standard-pipeline.ts +291 -18
  445. package/src/pipeline/standard-post.ts +90 -24
  446. package/src/pipeline-builder.ts +1 -1
  447. package/src/plugin.ts +4 -0
  448. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  449. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  450. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  451. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  452. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  453. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  454. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  455. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  456. package/src/record/barrel-distortion-frame.ts +110 -0
  457. package/src/record/dynamic-geometry-consumption.ts +39 -9
  458. package/src/record/fold-buckets.ts +852 -0
  459. package/src/record/fold-instance-buffer.ts +51 -0
  460. package/src/record/frame-lighting.ts +36 -2
  461. package/src/record/frame-snapshot.ts +39 -3
  462. package/src/record/frame.ts +217 -1084
  463. package/src/record/gpu-draw-receipts.ts +38 -0
  464. package/src/record/gpu-timing.ts +48 -5
  465. package/src/record/main-pass-geometry.ts +251 -82
  466. package/src/record/main-pass-material.ts +66 -4
  467. package/src/record/main-pass-sprite-draws.ts +7 -65
  468. package/src/record/main-pass.ts +156 -20
  469. package/src/record/motion-blur-receipt.ts +91 -0
  470. package/src/record/probe-blend-buffer.ts +180 -0
  471. package/src/record/recovery-pipeline.ts +35 -3
  472. package/src/record/render-context.ts +39 -3
  473. package/src/record/shadow-pass.ts +30 -1
  474. package/src/record/skybox-post-pass.ts +28 -4
  475. package/src/record/typed-frame-graph.ts +770 -134
  476. package/src/record/view-ubo.ts +26 -3
  477. package/src/record/volume-params.ts +225 -0
  478. package/src/recovery/render-system-candidate.ts +235 -42
  479. package/src/reflection/record-owner.ts +7 -3
  480. package/src/render-contract.ts +48 -4
  481. package/src/render-graph-primitives.ts +7 -1
  482. package/src/render-pipeline.ts +130 -0
  483. package/src/render-system-extract-tail.ts +57 -61
  484. package/src/render-system-extract.ts +74 -76
  485. package/src/render-system-presentation.ts +56 -0
  486. package/src/render-system-producer-roots.ts +96 -0
  487. package/src/render-system-residency.ts +159 -0
  488. package/src/render-system.ts +347 -363
  489. package/src/scene/probe-blend.ts +96 -4
  490. package/src/scene/render-scene.ts +349 -280
  491. package/src/ssao-buffers.ts +95 -2
  492. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  493. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  494. package/src/surface/dynamic-input.ts +658 -0
  495. package/src/surface/gpu-driven.ts +147 -0
  496. package/src/surface/submission-observation.ts +517 -0
  497. package/src/systems/skin-palette-allocator.ts +4 -1
  498. package/src/temporal/gpu.ts +101 -17
  499. package/src/temporal/inspection.ts +7 -1
  500. package/src/temporal/standard-scene-data.ts +5 -0
  501. package/src/temporal/target-coverage-attachment.ts +4 -0
  502. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  503. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  504. package/src/transmission/single-layer-medium.ts +322 -0
  505. package/src/typed-render-graph-primitives.ts +70 -2
  506. package/src/volume/component.ts +10 -9
  507. package/src/volume/extract.ts +11 -5
  508. package/src/volume/inspection.ts +3 -0
  509. package/src/volume/passes.ts +87 -4
  510. package/src/volume/resources.ts +2 -1
  511. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  512. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  513. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  514. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  515. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  516. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  517. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  518. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -1,8 +1,8 @@
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-LEAXOMYJ.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-3RTCJTH4.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-NB2S7ZRX.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
7
  import { RenderGraphError } from '@forgeax/engine-render-graph';
8
8
  import { ok as ok$1, err, RhiError } from '@forgeax/engine-rhi';
@@ -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 = {
@@ -1249,10 +1260,35 @@ function generateSsaoNoise(seed = 0) {
1249
1260
  var BYTES_PER_KERNEL_ELEMENT = 16;
1250
1261
  var UNIFORM_BYTES = 256;
1251
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
+ }
1252
1285
  function getOrCreateSsaoFallbackTexture(runtime) {
1253
1286
  const cached = fallbackCache.get(runtime);
1254
1287
  if (cached !== void 0 && cached.device === runtime.device) return cached;
1255
- if (cached !== void 0) fallbackCache.delete(runtime);
1288
+ if (cached !== void 0) {
1289
+ fallbackCache.delete(runtime);
1290
+ retireSsaoResources(cached.device, () => destroySsaoFallbackResources(runtime, cached));
1291
+ }
1256
1292
  const device = runtime.device;
1257
1293
  const texRes = device.createTexture({
1258
1294
  label: "hdrp-ssao-fallback-white",
@@ -1281,6 +1317,7 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1281
1317
  );
1282
1318
  if (!writeRes.ok) {
1283
1319
  runtime.errorRegistry.fire(writeRes.error);
1320
+ destroyTexture(runtime, device, texRes.value);
1284
1321
  return null;
1285
1322
  }
1286
1323
  const viewRes = device.createTextureView(texRes.value, {
@@ -1295,6 +1332,7 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1295
1332
  });
1296
1333
  if (!viewRes.ok) {
1297
1334
  runtime.errorRegistry.fire(viewRes.error);
1335
+ destroyTexture(runtime, device, texRes.value);
1298
1336
  return null;
1299
1337
  }
1300
1338
  const samplerRes = device.createSampler({
@@ -1308,6 +1346,7 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1308
1346
  });
1309
1347
  if (!samplerRes.ok) {
1310
1348
  runtime.errorRegistry.fire(samplerRes.error);
1349
+ destroyTexture(runtime, device, texRes.value);
1311
1350
  return null;
1312
1351
  }
1313
1352
  const resources = {
@@ -1320,10 +1359,35 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1320
1359
  return resources;
1321
1360
  }
1322
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
+ }
1323
1384
  function getOrCreateSsaoBuffers(runtime) {
1324
1385
  const cached = cache.get(runtime);
1325
1386
  if (cached !== void 0 && cached.device === runtime.device) return cached;
1326
- if (cached !== void 0) cache.delete(runtime);
1387
+ if (cached !== void 0) {
1388
+ cache.delete(runtime);
1389
+ retireSsaoResources(cached.device, () => destroySsaoBufferResources(runtime, cached));
1390
+ }
1327
1391
  const device = runtime.device;
1328
1392
  const kernelSamples = generateSsaoKernel();
1329
1393
  const kernelData = new Float32Array(SSAO_KERNEL_SAMPLE_COUNT * 4);
@@ -1347,6 +1411,7 @@ function getOrCreateSsaoBuffers(runtime) {
1347
1411
  const kernelWriteRes = device.queue.writeBuffer(kernelBufferRes.value, 0, kernelData);
1348
1412
  if (!kernelWriteRes.ok) {
1349
1413
  runtime.errorRegistry.fire(kernelWriteRes.error);
1414
+ destroyBuffer(runtime, device, kernelBufferRes.value);
1350
1415
  return null;
1351
1416
  }
1352
1417
  const noiseData = generateSsaoNoise();
@@ -1369,6 +1434,7 @@ function getOrCreateSsaoBuffers(runtime) {
1369
1434
  });
1370
1435
  if (!noiseTexRes.ok) {
1371
1436
  runtime.errorRegistry.fire(noiseTexRes.error);
1437
+ destroyBuffer(runtime, device, kernelBufferRes.value);
1372
1438
  return null;
1373
1439
  }
1374
1440
  const noiseCopyRes = device.queue.writeTexture(
@@ -1383,6 +1449,7 @@ function getOrCreateSsaoBuffers(runtime) {
1383
1449
  );
1384
1450
  if (!noiseCopyRes.ok) {
1385
1451
  runtime.errorRegistry.fire(noiseCopyRes.error);
1452
+ destroyCreatedSsaoResources(runtime, device, [kernelBufferRes.value], [noiseTexRes.value]);
1386
1453
  return null;
1387
1454
  }
1388
1455
  const uniformBufRes = device.createBuffer({
@@ -1393,6 +1460,7 @@ function getOrCreateSsaoBuffers(runtime) {
1393
1460
  });
1394
1461
  if (!uniformBufRes.ok) {
1395
1462
  runtime.errorRegistry.fire(uniformBufRes.error);
1463
+ destroyCreatedSsaoResources(runtime, device, [kernelBufferRes.value], [noiseTexRes.value]);
1396
1464
  return null;
1397
1465
  }
1398
1466
  const buffers = {
@@ -1689,7 +1757,7 @@ function createStandardSurfaceLightingBindGroup(runtime, layout, grid, ssaoOptio
1689
1757
  }
1690
1758
  return result.value;
1691
1759
  }
1692
- function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssaoOptions = { enabled: false }) {
1760
+ function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssaoOptions = { enabled: false }, meshBindingBytes = MESH_PER_ENTITY_STRIDE) {
1693
1761
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
1694
1762
  if (fallback === null) return null;
1695
1763
  const ssaoTexView = ssaoOptions.enabled ? ssaoOptions.ssaoBlurredView : fallback.view;
@@ -1705,7 +1773,7 @@ function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssa
1705
1773
  value: {
1706
1774
  buffer: meshStorageBuffer,
1707
1775
  offset: 0,
1708
- size: MESH_PER_ENTITY_STRIDE
1776
+ size: meshBindingBytes
1709
1777
  }
1710
1778
  }
1711
1779
  },
@@ -1718,17 +1786,16 @@ function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssa
1718
1786
  }
1719
1787
  return result.value;
1720
1788
  }
1721
- 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) {
1722
1790
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
1723
1791
  if (fallback === null) return null;
1724
- const meshSize = MESH_PER_ENTITY_STRIDE;
1725
1792
  const result = runtime.device.createBindGroup({
1726
1793
  label: "hdrp-skin-unified-bg-group2",
1727
1794
  layout,
1728
1795
  entries: [
1729
1796
  ...createPbrSkinMeshBindGroupEntries(
1730
1797
  meshStorageBuffer,
1731
- meshSize,
1798
+ meshBindingBytes,
1732
1799
  paletteBuffer,
1733
1800
  paletteBindingWindowBytes
1734
1801
  ),
@@ -2445,7 +2512,7 @@ function computeProjectionMatrix(camera) {
2445
2512
  }
2446
2513
  return proj;
2447
2514
  }
2448
- var VIEW_UNIFORM_BYTES = 960;
2515
+ var VIEW_UNIFORM_BYTES = 1024;
2449
2516
  var POINTS_LINES_VIEW_BYTES = 160;
2450
2517
  var POINTS_LINES_VIEW_SLOT_STRIDE = 256;
2451
2518
  var POINTS_LINES_VIEW_SLOT_COUNT = 1024;
@@ -2509,7 +2576,7 @@ function writePointsLinesViewUbo(queue, buffer, camera, width, height, model, st
2509
2576
  const uploaded = queue.writeBuffer(buffer, byteOffset, payload);
2510
2577
  if (!uploaded.ok) throw uploaded.error;
2511
2578
  }
2512
- function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShadowSnapshots, temporalOrOffset, projectorSpotIndex) {
2579
+ function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShadowSnapshots, temporalOrOffset, projectorSpotIndex, cloudShadowProjection) {
2513
2580
  const byteOffset = typeof temporalOrOffset === "number" ? temporalOrOffset : 0;
2514
2581
  const resolvedTemporal = typeof temporalOrOffset === "number" ? void 0 : temporalOrOffset;
2515
2582
  const projMatrix = computeProjectionMatrix(camera);
@@ -2527,7 +2594,7 @@ function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShado
2527
2594
  }
2528
2595
  const mainProjection = mat4.create();
2529
2596
  mat4.multiply(mainProjection, jitteredProjection, viewMatrix);
2530
- const VIEW_PAYLOAD_FLOATS = 240;
2597
+ const VIEW_PAYLOAD_FLOATS = 256;
2531
2598
  const viewPayload = new Float32Array(VIEW_PAYLOAD_FLOATS);
2532
2599
  for (let i = 0; i < 16; i++) viewPayload[i] = mainProjection[i] ?? 0;
2533
2600
  viewPayload[16] = light.direction[0] ?? 0;
@@ -2576,6 +2643,20 @@ function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShado
2576
2643
  viewPayload[238] = ssr.maxRoughness;
2577
2644
  viewPayload[239] = 1;
2578
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
+ }
2579
2660
  if (lights.splitPlanes !== void 0) {
2580
2661
  for (let s = 0; s < 4; s++) {
2581
2662
  for (let lane = 0; lane < 4; lane++) {
@@ -2685,6 +2766,7 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2685
2766
  const b5View = atlasViewMaybe !== null ? atlasViewMaybe : pipelineState.shadowAtlasFallbackTextureView;
2686
2767
  const graphSpotShadowView = graphTargets?.spotShadow;
2687
2768
  const b8View = graphSpotShadowView !== void 0 ? graphSpotShadowView : pipelineState.shadowFallbackTextureView;
2769
+ const cloudShadowView = graphTargets?.cloudShadow ?? pipelineState.defaultWhiteTextureView;
2688
2770
  const extendedLighting = pipelineState.extendedLightingAvailable ?? true;
2689
2771
  const iesProfileTextureView = pipelineState.iesProfileTextureView;
2690
2772
  const cookieTextureView = pipelineState.cookieTextureView;
@@ -2716,6 +2798,7 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2716
2798
  extendedLightingResources.cookieMatrixBuffer
2717
2799
  ] : [];
2718
2800
  const projectorAvailable = pipelineState.projectorAvailable !== false;
2801
+ const lowLimitCloudBindings = !extendedLighting && !projectorAvailable;
2719
2802
  const b11View = graphTargets?.projector ?? pipelineState.defaultWhiteTextureView;
2720
2803
  const b12Sampler = graphTargets?.projectorSampler ?? pipelineState.defaultSampler;
2721
2804
  viewBindGroup = getOrCreateFromChain(
@@ -2729,7 +2812,8 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2729
2812
  b8View,
2730
2813
  ...extendedLightingViews,
2731
2814
  ...extendedLightingResources === void 0 && projectorAvailable ? [b11View, b12Sampler] : [],
2732
- pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer
2815
+ pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
2816
+ ...lowLimitCloudBindings ? [] : [cloudShadowView, pipelineState.defaultSampler]
2733
2817
  ],
2734
2818
  "view-main",
2735
2819
  () => {
@@ -2811,8 +2895,20 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2811
2895
  }
2812
2896
  },
2813
2897
  ...extendedLightingResources === void 0 && projectorAvailable ? [
2814
- { binding: 11, resource: { kind: "textureView", value: b11View } },
2815
- { 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
+ }
2816
2912
  ] : [],
2817
2913
  ...extendedLightingResources !== void 0 ? [
2818
2914
  {
@@ -2860,7 +2956,23 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2860
2956
  }
2861
2957
  }
2862
2958
  }
2863
- ] : []
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
+ ]
2864
2976
  // feat-20260625-spot-light-shadow-mapping w25: the per-spot
2865
2977
  // fragment-read lightViewProj matrices fold into the View UBO
2866
2978
  // (binding 0, `view.spotLightViewProj`) — no standalone binding 9
@@ -4295,6 +4407,42 @@ var GpuTexture = class {
4295
4407
  return r;
4296
4408
  }
4297
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
+ }
4298
4446
  var STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES = 18;
4299
4447
  function isOrdinaryMaterialVariant(variant) {
4300
4448
  return variant.defines.COVERAGE_ONLY !== true;
@@ -4403,7 +4551,7 @@ function deviceOptionsForAdapter(adapter, options) {
4403
4551
 
4404
4552
  // src/ibl/skylight-bind-group.ts
4405
4553
  var FALLBACK_BYTES_PER_ROW = 256;
4406
- function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmission, textureInjections = []) {
4554
+ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmission, textureInjections = [], surfaceMedium) {
4407
4555
  const iblStart = materialEntries.length;
4408
4556
  const result = [
4409
4557
  ...materialEntries,
@@ -4450,6 +4598,35 @@ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmis
4450
4598
  resource: { kind: "textureView", value: transmissionView }
4451
4599
  }
4452
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
+ }
4453
4630
  const physicalStart = 26;
4454
4631
  for (let index = 0; index < textureInjections.length; index += 1) {
4455
4632
  const resource = textureInjections[index];
@@ -4466,13 +4643,15 @@ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmis
4466
4643
  }
4467
4644
  );
4468
4645
  }
4469
- result.push({
4470
- binding: 47,
4471
- resource: {
4472
- kind: "textureView",
4473
- value: skylight.skylightPrefilterView ?? skylight.prefilterView
4474
- }
4475
- });
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
+ }
4476
4655
  return result;
4477
4656
  }
4478
4657
  function createSkylightFallback(device, queue) {
@@ -5277,8 +5456,8 @@ function recordIblMaterialBinding(frameState, materialBgl, bindGroup, entries, i
5277
5456
  errors: []
5278
5457
  };
5279
5458
  }
5280
- function isMaterialBgAssemblyCacheHit(cached, material, materialBgl, materialBuffer, skylightResources, materialResourceEpoch, transmissionBackdropView, sceneMaterialBuffer) {
5281
- 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;
5282
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;
5283
5462
  }
5284
5463
  function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWorld = deps.world, materialShaderId = submeshMaterial.materialShaderId) {
@@ -5294,6 +5473,9 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5294
5473
  materialBgShared,
5295
5474
  materialBgAssemblyCache,
5296
5475
  transmissionBackdropView,
5476
+ surfaceRawDepthView,
5477
+ surfaceNearestLayerView,
5478
+ surfaceNearestDepthView,
5297
5479
  bindGroupCounts,
5298
5480
  frameState
5299
5481
  } = deps;
@@ -5303,6 +5485,35 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5303
5485
  const materialCacheKey = smMaterialHandle === void 0 ? void 0 : `${materialWorld.identity}:${smMaterialHandle}:${materialShaderId ?? ""}:${selectedProbe?.probeIndex ?? "sky"}`;
5304
5486
  const smHasVideoFields = (submeshMaterial.videoTextureFields?.size ?? 0) > 0;
5305
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
+ }
5306
5517
  const smSchema = (smShaderId !== void 0 ? runtime.getParamSchema?.(smShaderId) : void 0) ?? submeshMaterial.materialParamSchema;
5307
5518
  const smPerShaderBgl = smShaderId !== void 0 ? runtime.getMaterialBindGroupLayout?.(smShaderId, smSchema) : void 0;
5308
5519
  const smMaterialBgl = smPerShaderBgl ?? pipelineState.materialBindGroupLayout;
@@ -5322,7 +5533,8 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5322
5533
  effectiveSkylightResources,
5323
5534
  store.materialResourceEpoch,
5324
5535
  transmissionBackdropView,
5325
- sceneMaterialBuffer
5536
+ sceneMaterialBuffer,
5537
+ surfaceRawDepthView
5326
5538
  )) {
5327
5539
  if (diagnosticsEnabled) {
5328
5540
  recordIblMaterialBinding(
@@ -5464,14 +5676,16 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5464
5676
  });
5465
5677
  }
5466
5678
  const transmissionSampler = transmissionBackdropView != null ? effectiveSkylightResources.prefilterSampler : pipelineState.defaultSampler;
5679
+ const keepMediumBackdropSlots = surfaceMediumResources !== void 0;
5467
5680
  const smMergedEntries = assembleMaterialWithSkylightEntries(
5468
5681
  smBaseEntries,
5469
5682
  effectiveSkylightResources,
5470
- transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage) ? {
5683
+ transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage) || keepMediumBackdropSlots ? {
5471
5684
  sampler: transmissionSampler,
5472
- ...transmissionBackdropView === void 0 ? {} : { backdropView: transmissionBackdropView }
5685
+ ...transmissionBackdropView === void 0 ? { backdropView: pipelineState.defaultWhiteTextureView } : { backdropView: transmissionBackdropView }
5473
5686
  } : null,
5474
- physicalTextureInjections
5687
+ physicalTextureInjections,
5688
+ surfaceMediumResources
5475
5689
  );
5476
5690
  if (runtime.device.caps.storageBuffer) {
5477
5691
  smMergedEntries.push({
@@ -5500,6 +5714,14 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5500
5714
  entityKey,
5501
5715
  materialHandle: smMaterialHandle,
5502
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
+ },
5503
5725
  paramSnapshot: submeshMaterial.paramSnapshot,
5504
5726
  handleTypes: materialCacheHandles.map((handle) => typeof handle)
5505
5727
  })}`
@@ -5615,6 +5837,111 @@ function prepareMaterialSkylight(c) {
5615
5837
  );
5616
5838
  }
5617
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
+
5618
5945
  // src/record/main-pass-geometry.ts
5619
5946
  function sameOpaqueTemporalDraw(a, b) {
5620
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);
@@ -5666,9 +5993,10 @@ function isGpuDrivenMainClaimedSubmesh(c, source, submeshIndex, drawIndices) {
5666
5993
  if (drawItemIndex === void 0 || draw === void 0) return false;
5667
5994
  const material = source.materials[draw.materialSlot] ?? source.material;
5668
5995
  const sourceDrawItemIndex = gpuDrivenSourceDrawItemIndex(draw, drawItemIndex);
5996
+ const stableWorld = c.gpuDrivenWorldKeys?.[source.worldId] ?? source.worldId;
5669
5997
  return c.gpuDrivenDrawKeys?.has(
5670
5998
  gpuDrivenDrawKey(
5671
- worldEntityKey(source.worldId, source.entityKey),
5999
+ worldEntityKey(stableWorld, source.entityKey),
5672
6000
  material.materialHandle ?? -1,
5673
6001
  sourceDrawItemIndex
5674
6002
  )
@@ -5754,6 +6082,9 @@ function geometryRenderStateForPass(base, passKind, coverageOnly = false) {
5754
6082
  depthCompare: "less-equal"
5755
6083
  };
5756
6084
  }
6085
+ function authoredTransparentDepthWrite(transparent, renderState) {
6086
+ return (transparent === true || renderState?.blend !== void 0) && renderState?.depthWriteEnabled === true;
6087
+ }
5757
6088
  function geometryRecordPhase(passKind, segment) {
5758
6089
  const pass = passKind === "deferred" ? "g-buffer" : "forward";
5759
6090
  return `record/graph-execute/${pass}/${segment}`;
@@ -5768,13 +6099,16 @@ function submitSubmeshDraws(pass, state, pipeline, instanceDraws, indexed, index
5768
6099
  state.pipeline = pipeline;
5769
6100
  }
5770
6101
  for (const instanceDraw of instanceDraws) {
5771
- if (instanceDraw.instanceBuffer !== state.instancesBuffer || instanceDraw.probeOffset !== state.probeOffset) {
5772
- 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) {
5773
6106
  pass.setBindGroup(3, instanceDraw.instanceBindGroup);
5774
6107
  } else {
5775
6108
  pass.setBindGroup(3, instanceDraw.instanceBindGroup, [instanceDraw.probeOffset]);
5776
6109
  }
5777
6110
  state.instancesBuffer = instanceDraw.instanceBuffer;
6111
+ state.instanceBindGroup = instanceDraw.instanceBindGroup;
5778
6112
  state.probeOffset = instanceDraw.probeOffset;
5779
6113
  }
5780
6114
  if (indexed) {
@@ -5782,7 +6116,7 @@ function submitSubmeshDraws(pass, state, pipeline, instanceDraws, indexed, index
5782
6116
  } else {
5783
6117
  pass.draw(vertexCount, instanceDraw.instanceCount, 0, 0);
5784
6118
  }
5785
- onDraw?.();
6119
+ onDraw?.(instanceDraw, indexed ? "draw-indexed" : "draw");
5786
6120
  }
5787
6121
  }
5788
6122
  function recordPointsLinesDraw(pass, plan) {
@@ -5793,7 +6127,7 @@ function recordPointsLinesDraw(pass, plan) {
5793
6127
  }
5794
6128
  pass.draw(plan.vertexCount, 1, 0, 0);
5795
6129
  }
5796
- 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) {
5797
6131
  const {
5798
6132
  runtime,
5799
6133
  pipelineState,
@@ -5829,6 +6163,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5829
6163
  const bindingState = {
5830
6164
  pipeline: null,
5831
6165
  instancesBuffer: null,
6166
+ instanceBindGroup: null,
5832
6167
  probeOffset: -1
5833
6168
  };
5834
6169
  const identityInstanceBuffer = pipelineState.identityInstanceBuffer;
@@ -5848,7 +6183,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5848
6183
  const recordOcclusionCandidate = (draw) => {
5849
6184
  draw();
5850
6185
  };
5851
- 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) => {
5852
6187
  const pipelineVariantSet = withCoverageVariant(variantSet);
5853
6188
  const reflectionFallbackFormats = materialShaderId === "forgeax::default-standard-pbr" && c.reflectionFallbackColorFormat !== void 0 ? passKind === "deferred" ? colorFormats.slice(1) : [c.reflectionFallbackColorFormat] : void 0;
5854
6189
  const renderStateKey = renderStateHash(renderState);
@@ -5856,12 +6191,12 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5856
6191
  const cachedLookups = shaderLookupCache?.get(renderStateKey);
5857
6192
  if (cachedLookups !== void 0) {
5858
6193
  for (const cached of cachedLookups) {
5859
- 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(",")) {
5860
6195
  return cached.handle;
5861
6196
  }
5862
6197
  }
5863
6198
  }
5864
- 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);
5865
6200
  if (!resolvedVariantSetResult.ok) {
5866
6201
  runtime.errorRegistry.fire(resolvedVariantSetResult.error);
5867
6202
  return null;
@@ -5884,7 +6219,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5884
6219
  void 0,
5885
6220
  layoutProjection,
5886
6221
  void 0,
5887
- void 0,
6222
+ layoutKind,
5888
6223
  void 0,
5889
6224
  reflectionFallbackFormats,
5890
6225
  vertexEntry,
@@ -5909,6 +6244,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5909
6244
  colorFormatOverride: colorFormat,
5910
6245
  additionalColorFormats: reflectionFallbackFormats,
5911
6246
  textureMask,
6247
+ layoutKind,
5912
6248
  handle
5913
6249
  };
5914
6250
  if (shaderLookupCache === void 0) {
@@ -5927,6 +6263,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5927
6263
  for (let i = 0; i < validatedOrdered.length; i++) {
5928
6264
  const entry = validatedOrdered[i];
5929
6265
  if (entry === void 0) continue;
6266
+ if (c.foldDispatchPlan?.skipIndices.has(i) === true) continue;
5930
6267
  const pointsLinesSubmission = c.pointsLines?.prepare(entry, clusteredLighting);
5931
6268
  if (entry.source.pointsLines !== void 0 && pointsLinesSubmission?.plan.drawCount !== 1)
5932
6269
  continue;
@@ -6009,8 +6346,17 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6009
6346
  }
6010
6347
  }
6011
6348
  dispatchCounts.unlit += 1;
6012
- const instanceDraws = resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, false);
6013
- 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;
6014
6360
  let group2BindGroup = meshGroup2;
6015
6361
  meshGroup2DynamicOffsets[0] = i * MESH_PER_ENTITY_STRIDE;
6016
6362
  let group2DynamicOffsets = meshGroup2DynamicOffsets;
@@ -6153,10 +6499,11 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6153
6499
  if (passKind === "forward" && isGpuDrivenMainClaimedSubmesh(c, entry.source, smIdx, gpuDrivenDrawIndices)) {
6154
6500
  continue;
6155
6501
  }
6156
- 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 ?? [];
6157
6504
  for (const selectedPass of draws) {
6158
6505
  const vertexEntry = passKind === "temporal" ? void 0 : selectedPass?.vertexEntry;
6159
- const fragmentEntry = passKind === "temporal" ? void 0 : selectedPass?.fragmentEntry;
6506
+ const fragmentEntry = passKind === "temporal" ? void 0 : fragmentEntryPoint ?? selectedPass?.fragmentEntry;
6160
6507
  const selectedShaderId = selectedPass === void 0 ? submeshMaterial.materialShaderId : selectedPass.materialShaderId;
6161
6508
  const selectedRenderState = selectedPass === void 0 ? submeshMaterial.renderState : selectedPass.renderState;
6162
6509
  const selectedStencil = (selectedPass === void 0 ? entry.stencilReference : selectedPass.stencilReference) ?? 0;
@@ -6202,7 +6549,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6202
6549
  pass.setBindGroup(1, perSubmeshBg, materialGroup1DynamicOffsets, 0, 1);
6203
6550
  const smTopology = sm.topology;
6204
6551
  const smMaterialShaderId = selectedPass !== void 0 ? selectedShaderId : entry.source.skin !== void 0 ? isStandardPbrSkinMaterialShader(submeshMaterial.materialShaderId) ? submeshMaterial.materialShaderId : SKIN_MATERIAL_SHADER_ID : submeshMaterial.materialShaderId;
6205
- const probeBlendAvailable = probeBlendRecordAvailable && isStandardPbrMaterialShader(smMaterialShaderId);
6552
+ const probeBlendAvailable = probeBlendRecordAvailable && (isStandardPbrMaterialShader(smMaterialShaderId) || submeshMaterial.surfaceModel === "single-layer-medium");
6206
6553
  const isSpriteShader = smMaterialShaderId === "forgeax::sprite" || smMaterialShaderId === "forgeax::sprite-lit";
6207
6554
  const basePipelineRenderState = isSpriteShader ? {
6208
6555
  ...selectedRenderState,
@@ -6211,11 +6558,21 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6211
6558
  cullMode: "none",
6212
6559
  blend: selectedRenderState?.blend ?? SPRITE_PREMULTIPLIED_ALPHA_BLEND
6213
6560
  } : geometryRenderStateForTopology(smTopology, selectedRenderState);
6214
- const pipelineRenderState = geometryRenderStateForPass(
6561
+ let pipelineRenderState = geometryRenderStateForPass(
6215
6562
  basePipelineRenderState,
6216
6563
  passKind,
6217
6564
  coverageOnly
6218
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
+ }
6219
6576
  let smPipelineHandle;
6220
6577
  let materialGroup2Contract;
6221
6578
  let materialPipelineEntry = null;
@@ -6260,7 +6617,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6260
6617
  );
6261
6618
  const transmissionAvailable = requestsStandardTransmissionVariant(submeshMaterial);
6262
6619
  const materialCapabilityVariantSet = transmissionAvailable && !capabilityVariantSet.includes("TRANSMISSION_AVAILABLE=") ? `${capabilityVariantSet}+TRANSMISSION_AVAILABLE=true` : capabilityVariantSet;
6263
- 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}`;
6264
6621
  const cachedPipeline = resolveMaterialPipeline(
6265
6622
  smMaterialShaderId,
6266
6623
  pipelineRenderState,
@@ -6271,7 +6628,8 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6271
6628
  entry.mesh.layoutProjection,
6272
6629
  vertexEntry,
6273
6630
  fragmentEntry,
6274
- 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
6275
6633
  );
6276
6634
  materialPipelineEntry = cachedPipeline;
6277
6635
  smPipelineHandle = cachedPipeline?.pipeline ?? null;
@@ -6291,13 +6649,18 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6291
6649
  }
6292
6650
  continue;
6293
6651
  }
6294
- 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(
6295
6658
  c,
6296
6659
  entry,
6297
- identityInstanceDraws,
6298
- probeBlendAvailable
6299
- );
6300
- if (instanceDraws2 === null) continue;
6660
+ sourceDrawItemIndex,
6661
+ resolvedInstanceDraws
6662
+ ) : resolvedInstanceDraws;
6663
+ if (instanceDraws === null) continue;
6301
6664
  if (!isSkinEntry) {
6302
6665
  materialGroup2Contract = materialPipelineEntry?.group2Contract;
6303
6666
  if (materialGroup2Contract === void 0) continue;
@@ -6339,12 +6702,29 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6339
6702
  pass,
6340
6703
  bindingState,
6341
6704
  smPipelineHandle,
6342
- instanceDraws2,
6705
+ instanceDraws,
6343
6706
  entry.mesh.indexed,
6344
6707
  sm.indexCount,
6345
6708
  sm.vertexCount,
6346
6709
  sm.indexOffset,
6347
- () => 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
+ }
6348
6728
  )
6349
6729
  );
6350
6730
  } else {
@@ -6357,12 +6737,29 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6357
6737
  pass,
6358
6738
  bindingState,
6359
6739
  smPipelineHandle,
6360
- instanceDraws2,
6740
+ instanceDraws,
6361
6741
  entry.mesh.indexed,
6362
6742
  sm.indexCount,
6363
6743
  sm.vertexCount,
6364
6744
  sm.indexOffset,
6365
- () => 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
+ }
6366
6763
  )
6367
6764
  )
6368
6765
  );
@@ -6574,8 +6971,10 @@ function resolveStorageInstanceChunks(c, entry, inst, cap, probeBuffer, probeOff
6574
6971
  activeBuffer.buffer.handle,
6575
6972
  probeBuffer
6576
6973
  ),
6974
+ ...probeBuffer === void 0 ? {} : { probeBuffer },
6577
6975
  probeOffset,
6578
- instanceCount: count
6976
+ instanceCount: count,
6977
+ firstInstanceOrdinal: start
6579
6978
  });
6580
6979
  }
6581
6980
  if (chunks !== void 0) {
@@ -6617,6 +7016,7 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6617
7016
  pipelineState.identityInstanceBuffer,
6618
7017
  probeBinding?.buffer
6619
7018
  ),
7019
+ ...probeBinding?.buffer === void 0 ? {} : { probeBuffer: probeBinding.buffer },
6620
7020
  probeOffset: probeBinding?.offset ?? -1
6621
7021
  }
6622
7022
  ];
@@ -6729,8 +7129,10 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6729
7129
  active.buffer.handle,
6730
7130
  probeBinding?.buffer
6731
7131
  ),
7132
+ ...probeBinding?.buffer === void 0 ? {} : { probeBuffer: probeBinding.buffer },
6732
7133
  probeOffset: probeBinding?.offset ?? -1,
6733
- instanceCount: count
7134
+ instanceCount: count,
7135
+ firstInstanceOrdinal: start
6734
7136
  });
6735
7137
  }
6736
7138
  if (chunks !== void 0) {
@@ -6784,6 +7186,7 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6784
7186
  if (!bufRes.ok) {
6785
7187
  runtime.errorRegistry.fire(bufRes.error);
6786
7188
  reportInstanceFailure(c, inst, bufRes.error, requestedBytes, cap);
7189
+ return null;
6787
7190
  } else {
6788
7191
  if (cached !== void 0 && !cached.buffer.isDestroyed) {
6789
7192
  const r = cached.buffer.destroy();
@@ -6860,43 +7263,61 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6860
7263
  {
6861
7264
  instanceBuffer,
6862
7265
  instanceBindGroup: resolveGeometryInstancesBindGroup(c, instanceBuffer, probeBinding?.buffer),
7266
+ ...probeBinding?.buffer === void 0 ? {} : { probeBuffer: probeBinding.buffer },
6863
7267
  probeOffset: probeBinding?.offset ?? -1,
6864
7268
  instanceCount
6865
7269
  }
6866
7270
  ];
6867
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
+ }
6868
7312
  function resolveProbeBlendBuffer(c, record, entityKey) {
6869
7313
  const { runtime, frameState } = c;
6870
- const usage = runtime.device.caps.storageBuffer ? GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST : GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
6871
7314
  if (record === void 0) throw new Error("probe blend record is required for probe allocation");
6872
7315
  if (entityKey === void 0) throw new Error("probe blend record requires an entity key");
6873
- const offset = probeBlendRecordOffset(record.objectKey);
6874
- const requiredCapacity = record.objectKey + 2;
6875
- let buffer = frameState.probeBlendRecordBuffer;
6876
- if (buffer === void 0 || frameState.probeBlendRecordBufferCapacity < requiredCapacity) {
6877
- const created = runtime.device.createBuffer({
6878
- label: "probe-blend-records",
6879
- size: requiredCapacity * PROBE_BLEND_RECORD_STRIDE,
6880
- usage,
6881
- mappedAtCreation: false
6882
- });
6883
- if (!created.ok) throw created.error;
6884
- buffer = new GpuBuffer(runtime.device, created.value);
6885
- frameState.probeBlendRecordBuffer = buffer;
6886
- frameState.probeBlendRecordBufferCapacity = requiredCapacity;
6887
- frameState.probeBlendBuffers.clear();
6888
- }
6889
- const cached = frameState.probeBlendBuffers.get(entityKey);
6890
- const unchanged = cached !== void 0 && cached.generation === record.generation && cached.bytes.length === record.bytes.length && cached.bytes.every((value, index) => value === record.bytes[index]);
6891
- if (!unchanged) {
6892
- const uploaded = runtime.device.queue.writeBuffer(buffer.handle, offset, record.bytes);
6893
- if (!uploaded.ok) throw uploaded.error;
6894
- frameState.probeBlendBuffers.set(entityKey, {
6895
- generation: record.generation,
6896
- bytes: new Uint8Array(record.bytes)
6897
- });
6898
- }
6899
- 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) };
6900
7321
  }
6901
7322
  function resolveGeometryInstancesBindGroup(c, instanceBuffer, probeBuffer) {
6902
7323
  const { runtime, pipelineState, frameState, bindGroupCounts } = c;
@@ -7219,50 +7640,10 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, resolveMaterialB
7219
7640
  const spriteInst = spriteEntry.source.instances;
7220
7641
  const useFold = foldHeadBucket !== void 0 && spriteInst === void 0;
7221
7642
  if (useFold && foldHeadBucket !== void 0) {
7222
- const bucketCacheKey = -1 - ((foldHeadBucket.materialHandle & 65535) << 16 | i & 65535);
7223
- const uniformFallback = runtime.device.caps.storageBuffer === false;
7224
- const bucketPayload = uniformFallback ? foldHeadBucket.transforms : packInstanceStorageBuffer(foldHeadBucket.transforms);
7225
- const bucketBytes = bucketPayload.byteLength;
7226
- const bucketBufUsage = uniformFallback ? GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST : GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
7227
- const cachedBucket = frameState.instanceBuffers.get(bucketCacheKey);
7228
- let activeBucket = null;
7229
- if (cachedBucket !== void 0 && cachedBucket.uploadedArchVersion === foldHeadBucket.bucketSize && cachedBucket.uploadedByteLength === bucketBytes) {
7230
- activeBucket = cachedBucket;
7231
- } else if (bucketBytes > 0) {
7232
- const bufRes = runtime.device.createBuffer({
7233
- size: bucketBytes,
7234
- usage: bucketBufUsage,
7235
- mappedAtCreation: false
7236
- });
7237
- if (!bufRes.ok) {
7238
- runtime.errorRegistry.fire(bufRes.error);
7239
- } else {
7240
- if (cachedBucket !== void 0 && !cachedBucket.buffer.isDestroyed) {
7241
- const r = cachedBucket.buffer.destroy();
7242
- if (!r.ok) runtime.errorRegistry.fire(r.error);
7243
- }
7244
- const newBuf = new GpuBuffer(runtime.device, bufRes.value);
7245
- activeBucket = {
7246
- buffer: newBuf,
7247
- uploadedArchVersion: foldHeadBucket.bucketSize,
7248
- uploadedByteLength: bucketBytes
7249
- };
7250
- frameState.instanceBuffers.set(bucketCacheKey, activeBucket);
7251
- }
7252
- }
7253
- if (activeBucket !== null) {
7254
- const writeRes = runtime.device.queue.writeBuffer(
7255
- activeBucket.buffer.handle,
7256
- 0,
7257
- bucketPayload
7258
- );
7259
- if (!writeRes.ok) {
7260
- runtime.errorRegistry.fire(writeRes.error);
7261
- } else {
7262
- spriteInstanceBuffer = activeBucket.buffer.handle;
7263
- spriteInstanceCount = foldHeadBucket.bucketSize;
7264
- }
7265
- }
7643
+ const buffer = resolveFoldInstanceBuffer(c, foldHeadBucket, i);
7644
+ if (buffer === null) continue;
7645
+ spriteInstanceBuffer = buffer;
7646
+ spriteInstanceCount = foldHeadBucket.bucketSize;
7266
7647
  } else if (spriteInst !== void 0) {
7267
7648
  const uniformFallback = runtime.device.caps.storageBuffer === false;
7268
7649
  let spriteBufUsage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
@@ -7288,7 +7669,7 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, resolveMaterialB
7288
7669
  );
7289
7670
  spritePass.setBindGroup(3, spriteInstBg);
7290
7671
  spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
7291
- c.onRenderableDraw?.(spriteEntry);
7672
+ c.onRenderableDraw?.(spriteEntry, 0);
7292
7673
  continue;
7293
7674
  }
7294
7675
  spriteBufUsage = GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
@@ -7383,7 +7764,7 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, resolveMaterialB
7383
7764
  spritePass.setBindGroup(1, spritePassBg, [materialSlot * MATERIAL_PER_ENTITY_STRIDE]);
7384
7765
  spritePass.setBindGroup(3, spriteInstancesBg);
7385
7766
  spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
7386
- c.onRenderableDraw?.(spriteEntry);
7767
+ c.onRenderableDraw?.(spriteEntry, 0);
7387
7768
  }
7388
7769
  }
7389
7770
  function resolveSpriteInstancesBuffer(c, spriteEntry, fallbackBuffer, fallbackCount) {
@@ -7668,6 +8049,29 @@ function selectLod(input) {
7668
8049
 
7669
8050
  // src/gpu-driven/batch-topology.ts
7670
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
+ }
7671
8075
  var submissionCandidateMembershipCache = /* @__PURE__ */ new WeakMap();
7672
8076
  function buildSubmissionCandidateMembership(source) {
7673
8077
  const cached = submissionCandidateMembershipCache.get(source);
@@ -7766,7 +8170,8 @@ function eligibleDraws(slot) {
7766
8170
  materialResourceClass: draw.materialResourceClass,
7767
8171
  preparedIdentity,
7768
8172
  resourceIdentity: draw.materialResourceClass,
7769
- admission
8173
+ admission,
8174
+ materialPass: material.deferredPass === true ? "deferred" : "forward-only"
7770
8175
  },
7771
8176
  prepared,
7772
8177
  ...candidatePayload(draw, snapshot)
@@ -8034,6 +8439,7 @@ var BatchTopology = class {
8034
8439
  inspect() {
8035
8440
  let candidateCount = 0;
8036
8441
  for (const batch of this.batches.values()) candidateCount += batch.candidates.size;
8442
+ const resourceClasses = inspectResourceClassSplits(this.plan());
8037
8443
  return {
8038
8444
  revision: this.revision,
8039
8445
  batchCount: this.batches.size,
@@ -8045,7 +8451,10 @@ var BatchTopology = class {
8045
8451
  membershipChecks: this.membershipChecks,
8046
8452
  membershipAllocations: this.membershipAllocations,
8047
8453
  candidateAdds: this.candidateAdds,
8048
- candidateRemoves: this.candidateRemoves
8454
+ candidateRemoves: this.candidateRemoves,
8455
+ resourceClassCount: resourceClasses.resourceClassCount,
8456
+ resourceClassSplits: resourceClasses.resourceClassSplits,
8457
+ resourceClassSplitReasons: resourceClasses.resourceClassSplitReasons
8049
8458
  };
8050
8459
  }
8051
8460
  add(slot) {
@@ -8131,6 +8540,410 @@ var BatchTopology = class {
8131
8540
  };
8132
8541
  }
8133
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
+ }
8134
8947
 
8135
8948
  // src/scene/visibility/occlusion-confidence.ts
8136
8949
  function createConfidenceState() {
@@ -8482,6 +9295,7 @@ var COUNTER_WORDS = 2 + LOD_ROW_CAPACITY + 2;
8482
9295
  var GEOMETRY_WORK_COUNTER_OFFSET = 2 + LOD_ROW_CAPACITY;
8483
9296
  var ROOT_GEOMETRY_WORK_COUNTER_OFFSET = GEOMETRY_WORK_COUNTER_OFFSET + 1;
8484
9297
  var COUNTER_STRIDE = COUNTER_WORDS * 4;
9298
+ var INDIRECT_COMMAND_BYTES = 20;
8485
9299
  function selectGpuLodLane(caps) {
8486
9300
  return caps.compute && caps.storageBuffer && caps.indirectDrawing ? "gpu" : "cpu";
8487
9301
  }
@@ -8598,7 +9412,7 @@ fn selectLodLevel(
8598
9412
  @group(0) @binding(4) var<storage, read> batches: array<BatchRecord>;
8599
9413
  @group(0) @binding(5) var<uniform> view: ViewConstants;
8600
9414
  @group(0) @binding(6) var<storage, read_write> counters: array<atomic<u32>>;
8601
- @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>>;
8602
9416
  @group(0) @binding(8) var<storage, read_write> indirectArgs: array<u32>;
8603
9417
 
8604
9418
  fn counterIndex(batchIndex: u32) -> u32 { return batchIndex * ${COUNTER_WORDS}u; }
@@ -8683,9 +9497,11 @@ fn cullView(@builtin(global_invocation_id) id: vec3<u32>) {
8683
9497
  if ((candidate.materialSlot & 0x80000000u) != 0u) {
8684
9498
  materialOrPalette = instance.customDataStart;
8685
9499
  }
8686
- visibleIndices[candidate.visibleBase + localVisible] = vec2<u32>(
9500
+ visibleIndices[candidate.visibleBase + localVisible] = vec4<u32>(
8687
9501
  candidate.submitAdmission >> 1u,
8688
9502
  materialOrPalette,
9503
+ candidate.primitiveIndex + 1u,
9504
+ candidate.generation,
8689
9505
  );
8690
9506
  }
8691
9507
 
@@ -8708,10 +9524,22 @@ fn finalizeView(@builtin(global_invocation_id) id: vec3<u32>) {
8708
9524
  let candidate = candidates[batch.candidateBase];
8709
9525
  let selectedLod = selectLodLevel(candidate.projectedHeight, candidate.previousLevel, candidate.historyValid != 0u, candidate.lodRows, candidate.lodCount);
8710
9526
  let lod = candidate.lodRows[selectedLod];
8711
- 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;
8712
9540
  indirectArgs[args + 1u] = visibleCount;
8713
- indirectArgs[args + 2u] = select(batch.first, lod.firstIndex, candidate.lodCount > 0u && batch.indexed != 0u);
8714
- 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);
8715
9543
  indirectArgs[args + 4u] = 0u;
8716
9544
  }
8717
9545
  `
@@ -8773,6 +9601,8 @@ var GpuDrivenView = class _GpuDrivenView {
8773
9601
  bindGroupCreates = 0;
8774
9602
  bufferRebuilds = 0;
8775
9603
  resourceGeneration = 0;
9604
+ allocationLedger = new GpuResourceAllocationLedger();
9605
+ allocationTokens = /* @__PURE__ */ new WeakMap();
8776
9606
  /** The last readback copy that was actually encoded and is not consumed. */
8777
9607
  telemetryPending;
8778
9608
  /** Receipt identity for the copy pass encoded by the current frame. */
@@ -9013,7 +9843,8 @@ var GpuDrivenView = class _GpuDrivenView {
9013
9843
  viewConstantsUploadBytes: this.viewConstantsUploadBytes,
9014
9844
  bindGroupCreates: this.bindGroupCreates,
9015
9845
  bufferRebuilds: this.bufferRebuilds,
9016
- resourceGeneration: this.resourceGeneration
9846
+ resourceGeneration: this.resourceGeneration,
9847
+ resourceAllocation: this.allocationLedger.inspect()
9017
9848
  };
9018
9849
  }
9019
9850
  get visibleBuffer() {
@@ -9058,6 +9889,7 @@ var GpuDrivenView = class _GpuDrivenView {
9058
9889
  let overflow = false;
9059
9890
  let geometryWork = 0;
9060
9891
  let rootGeometryWork = 0;
9892
+ const actualMembers = [];
9061
9893
  const histogram = /* @__PURE__ */ new Map();
9062
9894
  for (let batchIndex = 0; batchIndex < plan.batches.length; batchIndex += 1) {
9063
9895
  const offset = batchIndex * COUNTER_STRIDE;
@@ -9066,6 +9898,26 @@ var GpuDrivenView = class _GpuDrivenView {
9066
9898
  values.getUint32(offset, true),
9067
9899
  plan.batches[batchIndex]?.visibleCapacity ?? 0
9068
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
+ }
9069
9921
  visible += batchVisible;
9070
9922
  overflow ||= batchOverflow;
9071
9923
  geometryWork += values.getUint32(offset + GEOMETRY_WORK_COUNTER_OFFSET * 4, true);
@@ -9079,7 +9931,16 @@ var GpuDrivenView = class _GpuDrivenView {
9079
9931
  return void 0;
9080
9932
  }
9081
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
+ });
9082
9942
  this.lodSelection = Object.freeze({
9943
+ resourceGeneration: copy.resourceGeneration,
9083
9944
  candidateCount,
9084
9945
  batchCount: plan.batches.length,
9085
9946
  // Selector-only batches remain in the plan/readback but the production
@@ -9121,6 +9982,9 @@ var GpuDrivenView = class _GpuDrivenView {
9121
9982
  ),
9122
9983
  geometryWork,
9123
9984
  rootGeometryWork,
9985
+ actualMembers: Object.freeze(actualMembers),
9986
+ ...surfaceReadback === void 0 ? {} : { surfaceReadback },
9987
+ ...surfaceIndirectReadback === void 0 ? {} : surfaceIndirectReadback.ok ? { surfaceIndirectParameters: surfaceIndirectReadback.value } : { surfaceIndirectReadbackError: surfaceIndirectReadback.error },
9124
9988
  ...copy.submit === void 0 ? {} : { submit: copy.submit }
9125
9989
  });
9126
9990
  this.telemetryPending = void 0;
@@ -9129,7 +9993,7 @@ var GpuDrivenView = class _GpuDrivenView {
9129
9993
  mapped.value.unmap();
9130
9994
  }
9131
9995
  }
9132
- addPasses(builder, labelPrefix = "gpu-driven", includeCompute = true) {
9996
+ addPasses(builder, labelPrefix = "gpu-driven", includeCompute = true, surfaceSubmissionObservation) {
9133
9997
  const buffers = this.buffers;
9134
9998
  const bindGroup = this.bindGroup;
9135
9999
  const plan = this.plan;
@@ -9209,14 +10073,14 @@ var GpuDrivenView = class _GpuDrivenView {
9209
10073
  const lodReadback = importBuffer(
9210
10074
  `${labelPrefix}.lod-selection-readback`,
9211
10075
  buffers.lodReadback,
9212
- this.batchCapacity * COUNTER_STRIDE,
10076
+ this.batchCapacity * COUNTER_STRIDE + this.visibleBufferCapacity * 16 + this.indirectCapacity * INDIRECT_COMMAND_BYTES,
9213
10077
  GPU_BUFFER_USAGE_MAP_READ | GPU_BUFFER_USAGE_COPY_DST
9214
10078
  );
9215
10079
  if (!lodReadback.ok) return lodReadback;
9216
10080
  const visible = importBuffer(
9217
10081
  `${labelPrefix}.visible`,
9218
10082
  buffers.visible,
9219
- this.visibleBufferCapacity * 8,
10083
+ this.visibleBufferCapacity * 16,
9220
10084
  GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC
9221
10085
  );
9222
10086
  if (!visible.ok) return visible;
@@ -9282,9 +10146,13 @@ var GpuDrivenView = class _GpuDrivenView {
9282
10146
  });
9283
10147
  if (!finalize.ok) return finalize;
9284
10148
  const graphResourceGeneration = this.resourceGeneration;
10149
+ const indirectReadbackOffset = this.batchCapacity * COUNTER_STRIDE + this.visibleBufferCapacity * 16;
10150
+ const indirectBufferIdentity = getOpaqueResourceIdentity(buffers.indirect);
9285
10151
  const readback = builder.addCopyPass(`${labelPrefix}.lod-selection-readback`, {
9286
10152
  accesses: [
9287
10153
  { resource: counters.value, usage: "copy-src" },
10154
+ { resource: visible.value, usage: "copy-src" },
10155
+ { resource: indirect.value, usage: "copy-src" },
9288
10156
  { resource: lodReadback.value, usage: "copy-dst" }
9289
10157
  ],
9290
10158
  encode: ({ encoder, resources }) => {
@@ -9295,12 +10163,32 @@ var GpuDrivenView = class _GpuDrivenView {
9295
10163
  resources.buffer(lodReadback.value).unwrap(),
9296
10164
  this.batchCapacity * COUNTER_STRIDE
9297
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
+ );
9298
10180
  const submittedPlan = this.plan;
9299
10181
  if (this.buffers === buffers && submittedPlan !== void 0 && this.resourceGeneration === graphResourceGeneration) {
10182
+ const submittedObservation = surfaceSubmissionObservation?.();
9300
10183
  this.telemetryPending = {
9301
10184
  buffers,
9302
10185
  plan: submittedPlan,
9303
10186
  resourceGeneration: graphResourceGeneration,
10187
+ indirectBufferIdentity,
10188
+ indirectReadbackOffset,
10189
+ ...submittedObservation === void 0 ? {} : {
10190
+ surfaceReadbackSnapshot: () => submittedObservation.gpuReadbackSnapshot()
10191
+ },
9304
10192
  ...this.telemetrySubmit === void 0 ? {} : { submit: this.telemetrySubmit }
9305
10193
  };
9306
10194
  }
@@ -9336,6 +10224,7 @@ var GpuDrivenView = class _GpuDrivenView {
9336
10224
  this.telemetrySubmit = void 0;
9337
10225
  this.lodSelectionReadback = void 0;
9338
10226
  this.lodSelection = void 0;
10227
+ for (const generation of buffers) this.retireGeneration(generation);
9339
10228
  this.destroyAfterSubmittedWork(buffers);
9340
10229
  void this.pipelineLayout;
9341
10230
  }
@@ -9372,6 +10261,7 @@ var GpuDrivenView = class _GpuDrivenView {
9372
10261
  const nextBatch = nextCapacity(batchCapacity);
9373
10262
  const nextIndirect = nextCapacity(indirectCapacity);
9374
10263
  const created = {};
10264
+ const createdTokens = [];
9375
10265
  const allocate = (name, size, usage) => {
9376
10266
  const buffer = this.device.createBuffer({
9377
10267
  label: `gpu-driven-view-${name}`,
@@ -9381,6 +10271,9 @@ var GpuDrivenView = class _GpuDrivenView {
9381
10271
  });
9382
10272
  if (!buffer.ok) return buffer;
9383
10273
  created[name] = buffer.value;
10274
+ const token = this.allocationLedger.allocate(size);
10275
+ this.allocationTokens.set(buffer.value, token);
10276
+ createdTokens.push(token);
9384
10277
  return ok$1(void 0);
9385
10278
  };
9386
10279
  const storage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC;
@@ -9404,7 +10297,7 @@ var GpuDrivenView = class _GpuDrivenView {
9404
10297
  storage: false
9405
10298
  },
9406
10299
  { name: "counters", size: nextBatch * COUNTER_STRIDE, usage: storage, storage: true },
9407
- { name: "visible", size: nextVisible * 8, usage: storage, storage: true },
10300
+ { name: "visible", size: nextVisible * 16, usage: storage, storage: true },
9408
10301
  {
9409
10302
  name: "indirect",
9410
10303
  size: nextIndirect * 20,
@@ -9413,7 +10306,7 @@ var GpuDrivenView = class _GpuDrivenView {
9413
10306
  },
9414
10307
  {
9415
10308
  name: "lodReadback",
9416
- size: nextBatch * COUNTER_STRIDE,
10309
+ size: nextBatch * COUNTER_STRIDE + nextVisible * 16 + nextIndirect * INDIRECT_COMMAND_BYTES,
9417
10310
  usage: GPU_BUFFER_USAGE_MAP_READ | GPU_BUFFER_USAGE_COPY_DST,
9418
10311
  storage: false
9419
10312
  }
@@ -9439,10 +10332,14 @@ var GpuDrivenView = class _GpuDrivenView {
9439
10332
  const result = allocate(request.name, request.size, request.usage);
9440
10333
  if (!result.ok) {
9441
10334
  for (const buffer of Object.values(created)) this.device.destroyBuffer(buffer);
10335
+ for (const token of createdTokens) this.allocationLedger.rollback(token);
9442
10336
  return result;
9443
10337
  }
9444
10338
  }
9445
- 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
+ }
9446
10343
  this.buffers = created;
9447
10344
  this.candidateCapacity = nextCandidate;
9448
10345
  this.visibleBufferCapacity = nextVisible;
@@ -9459,11 +10356,19 @@ var GpuDrivenView = class _GpuDrivenView {
9459
10356
  for (const buffers of generations) {
9460
10357
  for (const buffer of Object.values(buffers)) {
9461
10358
  this.device.destroyBuffer(buffer);
10359
+ const token = this.allocationTokens.get(buffer);
10360
+ if (token !== void 0) this.allocationLedger.release(token);
9462
10361
  }
9463
10362
  }
9464
10363
  };
9465
10364
  void this.device.queue.onSubmittedWorkDone().then(release, release);
9466
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
+ }
9467
10372
  };
9468
10373
 
9469
10374
  // src/gpu-driven/shadow-views.ts
@@ -9891,6 +10796,7 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
9891
10796
  );
9892
10797
  }
9893
10798
  const projectorAvailable = pipelineState.projectorAvailable !== false;
10799
+ const lowLimitCloudBindings = !extendedLighting && !projectorAvailable;
9894
10800
  try {
9895
10801
  return getOrCreateFromChain(
9896
10802
  frameState.viewBindGroupCache,
@@ -9903,7 +10809,8 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
9903
10809
  pipelineState.shadowCasterCascadeBuffer,
9904
10810
  pipelineState.shadowFallbackTextureView,
9905
10811
  ...extendedLighting ? extendedLightingCacheKeys : projectorAvailable ? [pipelineState.defaultWhiteTextureView, pipelineState.defaultSampler] : [],
9906
- pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer
10812
+ pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
10813
+ ...lowLimitCloudBindings ? [] : [pipelineState.defaultWhiteTextureView, pipelineState.defaultSampler]
9907
10814
  ],
9908
10815
  variant,
9909
10816
  () => {
@@ -9979,7 +10886,23 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
9979
10886
  binding: 12,
9980
10887
  resource: { kind: "sampler", value: pipelineState.defaultSampler }
9981
10888
  }
9982
- ] : []
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
+ ]
9983
10906
  ]
9984
10907
  });
9985
10908
  if (!created.ok) throw created.error;
@@ -10358,6 +11281,7 @@ function recordGpuDrivenShadowIfPublished(c, pass, identity) {
10358
11281
  visibleBindGroup: projection.visibleBindGroup,
10359
11282
  deformation: projection.deformation,
10360
11283
  materialGroup,
11284
+ ...batch.key.admission === "alpha-mask" ? { alphaMaskMaterialGroup: materialGroup } : {},
10361
11285
  vertexBuffer: projection.mesh.vertexBuffer.handle,
10362
11286
  ...batch.key.drawKind === "indexed" && projection.mesh.indexBuffer !== null ? {
10363
11287
  indexBuffer: projection.mesh.indexBuffer.handle,
@@ -11272,7 +12196,10 @@ function ensureGpuDrivenAlphaMaskMaterialBg(c, projection) {
11272
12196
  return bindGroup;
11273
12197
  }
11274
12198
  function ensureGpuDrivenCustomShadowMaterialBg(c, projection) {
11275
- 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;
11276
12203
  const fallback = c.pipelineState.skylightFallback;
11277
12204
  if (fallback === null) {
11278
12205
  throw new RhiError({
@@ -11334,18 +12261,23 @@ function isTransmissionMaterial(material) {
11334
12261
  return material.materialShaderId === "forgeax::default-standard-pbr" && typeof material.paramSnapshot?.transmission === "number" && material.paramSnapshot.transmission > 0;
11335
12262
  }
11336
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
+ }
11337
12268
  const transmission = isTransmissionMaterial(material);
11338
12269
  if (mode === "transmission") return transmission;
11339
- if (mode === "transparent") return material.transparent === true && !transmission;
11340
- return !transmission && material.transparent !== true;
12270
+ if (mode === "transparent") return material.transparent === true && !transmission && !medium;
12271
+ return !transmission && material.transparent !== true && !medium;
11341
12272
  }
11342
12273
  function matchedMaterialsForRecordMode(c, matchedMaterials, mode) {
11343
12274
  if (mode === void 0) return matchedMaterials;
12275
+ const surfaceMode = mode === "single-layer-medium-nearest-layer" || mode === "single-layer-medium-color";
11344
12276
  const filtered = /* @__PURE__ */ new Map();
11345
12277
  for (const entry of c.validatedOrdered) {
11346
12278
  const dispatchHandles = matchedMaterials?.get(entry.renderableIndex);
11347
- if (matchedMaterials !== null && dispatchHandles === void 0) continue;
11348
- 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));
11349
12281
  const handles = /* @__PURE__ */ new Set();
11350
12282
  for (const handle of candidateHandles) {
11351
12283
  const material = entry.source.materials.find((candidate) => (candidate.materialHandle ?? 0) === handle) ?? entry.source.material;
@@ -11388,11 +12320,14 @@ function recordMainPass(c, selector, options, graphPass) {
11388
12320
  const passKind = options?.passKind ?? "forward";
11389
12321
  const recordMode = options?.recordMode;
11390
12322
  const transmissionBackdropView = options?.transmissionBackdropView;
11391
- 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) {
11392
12327
  throw new RhiError({
11393
12328
  code: "webgpu-runtime-error",
11394
- expected: "transmissionBackdropView != null for transmission record mode",
11395
- 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"
11396
12331
  });
11397
12332
  }
11398
12333
  const colorViews = options?.colorViews ?? [geometryColorView];
@@ -11404,12 +12339,9 @@ function recordMainPass(c, selector, options, graphPass) {
11404
12339
  const videoHighPerfAvailable = probeVideoHighPerfUpload(runtime.device);
11405
12340
  const clusteredLighting = c.standardLighting?.kind === "clustered";
11406
12341
  const clusteredBindGroupMissing = validatedOrdered.length > 0 && !standardTopologyBindGroupReady(c.standardLighting, hdrpClusterBindGroup);
12342
+ const hdrpBuffers = clusteredLighting ? getOrCreateHdrpBuffers(runtime, frameState.installedPipelineConfig?.clusterGrid) : null;
11407
12343
  let hdrpSsaoBindGroup = null;
11408
- if (clusteredLighting && hdrpClusterBindGroup !== null && c.hdrpSsaoBlurredView !== void 0) {
11409
- const hdrpBuffers = getOrCreateHdrpBuffers(
11410
- runtime,
11411
- frameState.installedPipelineConfig?.clusterGrid
11412
- );
12344
+ if (hdrpClusterBindGroup !== null && c.hdrpSsaoBlurredView !== void 0) {
11413
12345
  if (hdrpBuffers !== null) {
11414
12346
  hdrpSsaoBindGroup = createHdrpUnifiedBindGroup(
11415
12347
  runtime,
@@ -11420,6 +12352,58 @@ function recordMainPass(c, selector, options, graphPass) {
11420
12352
  }
11421
12353
  }
11422
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
+ }
11423
12407
  let geometryPassEnded = false;
11424
12408
  const mainColorLoadOp = skyboxActive ? "load" : "clear";
11425
12409
  const mainPassResolves = passKind === "forward" && msaaActive && geometryColorResolveView !== null && !splitLdrSprite;
@@ -11577,7 +12561,10 @@ function recordMainPass(c, selector, options, graphPass) {
11577
12561
  ...gpuDrivenStandardPbrFrameResources?.sceneMaterialBuffer === void 0 && gpuDrivenSceneMaterialBuffer === void 0 ? {} : {
11578
12562
  sceneMaterialBuffer: gpuDrivenStandardPbrFrameResources?.sceneMaterialBuffer ?? gpuDrivenSceneMaterialBuffer
11579
12563
  },
11580
- ...transmissionBackdropView === void 0 ? {} : { transmissionBackdropView }
12564
+ ...transmissionBackdropView === void 0 ? {} : { transmissionBackdropView },
12565
+ ...surfaceRawDepthView === void 0 ? {} : { surfaceRawDepthView },
12566
+ ...surfaceNearestLayerView === void 0 ? {} : { surfaceNearestLayerView },
12567
+ ...surfaceNearestDepthView === void 0 ? {} : { surfaceNearestDepthView }
11581
12568
  };
11582
12569
  const buildPerSubmeshMaterialBg2 = (submeshMaterial, entityKey, materialWorld = world, materialShaderId = submeshMaterial.materialShaderId) => buildPerSubmeshMaterialBg(
11583
12570
  perSubmeshMaterialBgDeps,
@@ -11590,6 +12577,7 @@ function recordMainPass(c, selector, options, graphPass) {
11590
12577
  for (let materialSlot = 0; materialSlot < materialSlotCount; materialSlot += 1) {
11591
12578
  const material = materialSlots[materialSlot];
11592
12579
  if (material === void 0 || (material.videoTextureFields?.size ?? 0) > 0) continue;
12580
+ if (recordMode !== void 0 && !matchesRecordMode(material, recordMode)) continue;
11593
12581
  const owner = materialSlotOwners[materialSlot];
11594
12582
  if (owner === void 0) continue;
11595
12583
  preparedMaterialBindGroups[materialSlot] = buildPerSubmeshMaterialBg2(
@@ -11660,7 +12648,10 @@ function recordMainPass(c, selector, options, graphPass) {
11660
12648
  passKind,
11661
12649
  selectedDispatch,
11662
12650
  colorFormats,
11663
- 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
11664
12655
  );
11665
12656
  };
11666
12657
  if (c.profilePhase === void 0) {
@@ -11680,7 +12671,7 @@ function recordMainPass(c, selector, options, graphPass) {
11680
12671
  hint: "publish the current frame view/light/shadow bind group before GPU raster"
11681
12672
  });
11682
12673
  }
11683
- if (gpuDrivenStandardPbrFrameResources === void 0) {
12674
+ if (gpuDrivenStandardPbrFrameResources === void 0 || gpuDrivenStandardPbrFrameResources.materialBindGroups.length === 0) {
11684
12675
  throw new RhiError({
11685
12676
  code: "rhi-not-available",
11686
12677
  expected: "complete main-pass Standard PBR material bind-group receipt",
@@ -11691,7 +12682,9 @@ function recordMainPass(c, selector, options, graphPass) {
11691
12682
  viewBindGroup,
11692
12683
  pass,
11693
12684
  options.gpuDriven.resources,
11694
- gpuDrivenStandardPbrFrameResources
12685
+ gpuDrivenStandardPbrFrameResources,
12686
+ options.gpuDrivenFilter,
12687
+ options?.fragmentEntryPoint
11695
12688
  );
11696
12689
  }
11697
12690
  if (passKind === "forward" && recordMode === void 0) {
@@ -12049,7 +13042,7 @@ function recordBloomCompositePass(_c, resolve, graphPass) {
12049
13042
  stageBloomEncode(_c);
12050
13043
  if (graphPass === void 0) pass.end();
12051
13044
  }
12052
- function recordFxaaPass(c, resolve, graphPass, paramsOverride) {
13045
+ function recordFxaaPass(c, resolve, graphPass, paramsOverride, graphOutputFormat) {
12053
13046
  const { runtime, pipelineState, encoder, camera, currentTexture } = c;
12054
13047
  const fxaaActive = camera.antialias === "fxaa";
12055
13048
  if (fxaaActive && pipelineState.perPassResources.fxaaPipeline !== null && pipelineState.perPassResources.fxaaBindGroupLayout !== null && pipelineState.perPassResources.fxaaSampler !== null && runtime.getPostProcessParamsBuffer !== void 0) {
@@ -12096,7 +13089,7 @@ function recordFxaaPass(c, resolve, graphPass, paramsOverride) {
12096
13089
  },
12097
13090
  c.bindGroupCounts
12098
13091
  );
12099
- 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;
12100
13093
  let fxaaPass = graphPass;
12101
13094
  if (fxaaPass === void 0) {
12102
13095
  const fxaaOutputView = runtime.device.createTextureView(currentTexture, {
@@ -12115,7 +13108,19 @@ function recordFxaaPass(c, resolve, graphPass, paramsOverride) {
12115
13108
  )
12116
13109
  );
12117
13110
  }
12118
- 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);
12119
13124
  fxaaPass.setBindGroup(0, fxaaBg);
12120
13125
  fxaaPass.draw(3, 1, 0, 0);
12121
13126
  if (graphPass === void 0) fxaaPass.end();
@@ -12146,8 +13151,8 @@ function postProcessSourceDigest(source) {
12146
13151
  function postProcessShaderPipelineLabel(identity, source) {
12147
13152
  return `post-process-${identity}-pso-${postProcessSourceDigest(source)}`;
12148
13153
  }
12149
- function postProcessShaderModuleLabel(identity, source) {
12150
- return `${postProcessShaderPipelineLabel(identity, source)}-module`;
13154
+ function postProcessShaderModuleLabel(source) {
13155
+ return `post-process-module-${postProcessSourceDigest(source)}`;
12151
13156
  }
12152
13157
  function postProcessShaderEntrySignature(entry) {
12153
13158
  return JSON.stringify({
@@ -12157,7 +13162,9 @@ function postProcessShaderEntrySignature(entry) {
12157
13162
  byteSize: entry.params.byteSize,
12158
13163
  defaultValue: Array.from(entry.params.defaultValue)
12159
13164
  },
12160
- reads: entry.reads
13165
+ reads: entry.reads,
13166
+ usesView: entry.usesView,
13167
+ storageBindings: entry.storageBindings
12161
13168
  });
12162
13169
  }
12163
13170
  function isTemporalFullscreenBinding(values) {
@@ -12191,7 +13198,10 @@ var DEPTH_MIN_PARAMS_BYTE_SIZE = 16;
12191
13198
  function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12192
13199
  const { device } = ctx;
12193
13200
  const hasDepth = entryHasDepthRead(entry);
12194
- 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";
12195
13205
  const descriptor = buildBindGroupLayoutDescriptor(FULLSCREEN_DEFAULT_SPEC, { kind: bglKind });
12196
13206
  const colorReads = (entry.reads ?? []).filter(
12197
13207
  (read) => typeof read === "string" || read.sampleType !== "depth"
@@ -12205,6 +13215,14 @@ function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12205
13215
  texture: { sampleType: "float", viewDimension: "2d" }
12206
13216
  });
12207
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
+ }
12208
13226
  const bglRes = device.createBindGroupLayout(descriptor);
12209
13227
  if (!bglRes.ok) {
12210
13228
  ctx.errorRegistry.fire(bglRes.error);
@@ -12219,6 +13237,9 @@ function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12219
13237
  extraColorBindings: Object.freeze(
12220
13238
  Array.from({ length: extraColorCount }, (_, index) => firstExtraBinding + index)
12221
13239
  ),
13240
+ extraStorageBindings: Object.freeze(
13241
+ (entry.storageBindings ?? []).map((binding, index) => binding ?? firstStorageBinding + index)
13242
+ ),
12222
13243
  createHandle: (name, pipeline, paramsBuffer) => ({
12223
13244
  name,
12224
13245
  paramsBuffer,
@@ -12229,7 +13250,7 @@ function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12229
13250
  })
12230
13251
  };
12231
13252
  }
12232
- function createFullscreenBindGroup(device, bgl, inputView, sampler, paramsBuffer, depthTexView, depthSampler, additionalViews = []) {
13253
+ function createFullscreenBindGroup(device, bgl, inputView, sampler, paramsBuffer, depthTexView, depthSampler, additionalViews = [], additionalBuffers = []) {
12233
13254
  const entries = [
12234
13255
  { binding: 0, resource: { kind: "textureView", value: inputView } }
12235
13256
  ];
@@ -12249,6 +13270,12 @@ function createFullscreenBindGroup(device, bgl, inputView, sampler, paramsBuffer
12249
13270
  resource: { kind: "textureView", value: additional.view }
12250
13271
  });
12251
13272
  }
13273
+ for (const additional of additionalBuffers) {
13274
+ entries.push({
13275
+ binding: additional.binding,
13276
+ resource: { kind: "buffer", value: { buffer: additional.buffer } }
13277
+ });
13278
+ }
12252
13279
  const res = device.createBindGroup({
12253
13280
  label: "fullscreen-post-process-bg",
12254
13281
  layout: bgl,
@@ -12540,7 +13567,13 @@ function dispatchFullscreenPass(ctx, name, shader, color, reads, resolveCtx, com
12540
13567
  detail: { readsKey: reads[0] ?? "ldrColor", passName: name }
12541
13568
  });
12542
13569
  }
12543
- recordFxaaPass(requireRenderGraphRecordContext(ctx), resolveCtx, graphPass, paramsOverride);
13570
+ recordFxaaPass(
13571
+ requireRenderGraphRecordContext(ctx),
13572
+ resolveCtx,
13573
+ graphPass,
13574
+ paramsOverride,
13575
+ graphOutputFormat
13576
+ );
12544
13577
  return;
12545
13578
  }
12546
13579
  const lookup = ctx.runtime.lookupPostProcess;
@@ -12733,6 +13766,11 @@ var TEMPORAL_HISTORY_FORMATS = Object.freeze({
12733
13766
  temporal: "rgba16float",
12734
13767
  stability: "r8unorm"
12735
13768
  });
13769
+ var CLOUD_HISTORY_FORMATS = Object.freeze({
13770
+ radiance: "rgba16float",
13771
+ transmittance: "rgba16float",
13772
+ depth: "rgba16float"
13773
+ });
12736
13774
  function createSurface(device, childScope, label, width, height, format = TEMPORAL_HISTORY_FORMATS.color) {
12737
13775
  const texture = device.createTexture({
12738
13776
  label,
@@ -12756,8 +13794,15 @@ function createSurface(device, childScope, label, width, height, format = TEMPOR
12756
13794
  if (!view.ok) throw view.error;
12757
13795
  return { texture: texture.value, view: view.value };
12758
13796
  }
12759
- 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) {
12760
13804
  const childScope = scope.createChild(`${scope.owner}:temporal`);
13805
+ const cloudExtent = cloudHistoryExtent(width, height);
12761
13806
  try {
12762
13807
  return {
12763
13808
  device,
@@ -12808,6 +13853,59 @@ function createState(device, scope, width, height) {
12808
13853
  TEMPORAL_HISTORY_FORMATS.stability
12809
13854
  )
12810
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,
12811
13909
  bindGroupLayout: void 0,
12812
13910
  sampler: void 0,
12813
13911
  temporalSampler: void 0,
@@ -12842,16 +13940,17 @@ function getTemporalParamsBuffer(state) {
12842
13940
  state.paramsBuffer = created.value;
12843
13941
  return created.value;
12844
13942
  }
12845
- 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;
12846
13949
  const staged = frameState.temporalGpuState;
12847
- if (staged !== void 0 && staged.scope === scope && staged.width === width && staged.height === height) {
12848
- return staged;
12849
- }
13950
+ if (matches(staged)) return staged;
12850
13951
  const existing = frameState.activeTemporalGpuState;
12851
- if (existing !== void 0 && existing.scope === scope && existing.width === width && existing.height === height) {
12852
- return existing;
12853
- }
12854
- const next = createState(device, scope, width, height);
13952
+ if (matches(existing)) return existing;
13953
+ const next = createState(device, scope, width, height, wantsCloudHistory);
12855
13954
  frameState.temporalGpuState = next;
12856
13955
  return next;
12857
13956
  }
@@ -13135,7 +14234,11 @@ function addTypedScenePass(graph, options) {
13135
14234
  resource: target.view,
13136
14235
  usage: "sampled-read"
13137
14236
  })),
14237
+ ...options.cloudShadow === void 0 ? [] : [{ resource: options.cloudShadow.view, usage: "sampled-read" }],
13138
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" }] : [],
13139
14242
  ...options.environment === void 0 ? [] : [options.environment.irradiance, options.environment.prefilter].map((resource) => ({
13140
14243
  resource,
13141
14244
  usage: "sampled-read"
@@ -13177,8 +14280,12 @@ function addTypedScenePass(graph, options) {
13177
14280
  const internal = frame;
13178
14281
  const directionalShadow = options.directionalShadow === void 0 ? void 0 : resolvedView(resources, options.directionalShadow.view);
13179
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);
13180
14284
  const ssao = options.ssao === void 0 ? void 0 : resolvedView(resources, options.ssao.view);
13181
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);
13182
14289
  internal.frameState.currentDirectionalShadowView = directionalShadow ?? null;
13183
14290
  internal.frameState.currentSpotShadowView = spotShadow ?? null;
13184
14291
  const groups = buildPerFrameBindGroups(
@@ -13190,6 +14297,7 @@ function addTypedScenePass(graph, options) {
13190
14297
  {
13191
14298
  directionalShadow,
13192
14299
  spotShadow,
14300
+ cloudShadow,
13193
14301
  projector: internal.spotLightProjector?.view ?? internal.volumetricFog?.projectorView,
13194
14302
  projectorSampler: internal.spotLightProjector?.sampler ?? internal.volumetricFog?.projectorSampler
13195
14303
  },
@@ -13225,11 +14333,17 @@ function addTypedScenePass(graph, options) {
13225
14333
  passKind: options.passKind ?? "forward",
13226
14334
  ...options.clearColor === void 0 ? {} : { clearColor: options.clearColor },
13227
14335
  ...options.recordMode === void 0 ? {} : { recordMode: options.recordMode },
14336
+ ...options.transparentDepthWrite === void 0 ? {} : { transparentDepthWrite: options.transparentDepthWrite },
13228
14337
  ...options.coverageOnly === void 0 ? {} : { coverageOnly: options.coverageOnly },
13229
14338
  ...options.excludeSelector === void 0 ? {} : { excludeSelector: options.excludeSelector },
13230
14339
  ...options.includeSelector === void 0 ? {} : { includeSelector: options.includeSelector },
13231
14340
  ...options.transmissionBackdrop === void 0 ? {} : { transmissionBackdropView: transmissionBackdrop },
13232
- ...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 }
13233
14347
  });
13234
14348
  if (passContext.materialUboPayloadCache !== void 0) {
13235
14349
  internal.materialUboPayloadCache = passContext.materialUboPayloadCache;
@@ -13772,6 +14886,11 @@ function addStandardSceneDataPass(graph, target, depth) {
13772
14886
  color: target,
13773
14887
  depth,
13774
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",
13775
14894
  passKind: "temporal",
13776
14895
  // The temporal producer re-rasterizes the current scene after the main
13777
14896
  // color pass has populated depth. Its output is a semantic motion target;
@@ -13797,6 +14916,6 @@ function addTaaResolvePass(graph, current, currentTemporal, previousColor, previ
13797
14916
  });
13798
14917
  }
13799
14918
 
13800
- export { BLOOM_COMPOSITE_PARAMS_BYTES, BLOOM_DOWNSAMPLE_PARAMS_BYTES, BLOOM_UPSAMPLE_PARAMS_BYTES, 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, DEPTH_TEXTURE_FORMAT, FALLBACK_BYTES_PER_ROW, GPU_DRIVEN_VIEW_WGSL, GPU_SCENE_LAYOUTS, GpuBuffer, GpuDrivenView, GpuTexture, HDR_COLOR_ATTACHMENT_FORMAT, MATERIAL_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, 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, 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, standardBloomAdmitted, standardStorageVariantSet, standardTemporalLaneAdmission, standardTemporalPostOrder, standardTopologyVariantSet, temporalReadIndex, temporalWriteIndex, transmissionBackdropAvailable, uploadMeshSsboBatch, variantSetFromDefines, variantSetFromVertexLayoutProjection, warnMultiSkybox, warnMultiSkylight, warnZeroLightStandard, writeHdrpClusterAndSsaoBuffers, writePbrMaterialUboPayload, writePointsLinesViewUbo, writeShadowCasterUniforms, writeShadowParamsBuffer, writeSpotModifierTextures, writeViewUbo };
13801
- //# sourceMappingURL=chunk-VOZWDM3L.mjs.map
13802
- //# sourceMappingURL=chunk-VOZWDM3L.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