@forgeax/engine-render 0.1.33 → 0.1.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/README.md +1062 -127
  2. package/dist/assembly/backend-contract.d.ts +2 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  5. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  6. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  7. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  8. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  9. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  10. package/dist/assembly/device-feature-admission.d.ts +2 -2
  11. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  12. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  15. package/dist/assembly/factory.d.ts +1 -1
  16. package/dist/assembly/factory.d.ts.map +1 -1
  17. package/dist/assembly/host-contract.d.ts +6 -5
  18. package/dist/assembly/host-contract.d.ts.map +1 -1
  19. package/dist/assembly/material/assembly.d.ts.map +1 -1
  20. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  21. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  22. package/dist/assembly/material-shader-policy.d.ts +16 -2
  23. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  24. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  26. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  27. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  28. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  29. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  30. package/dist/assembly/render-target-host.d.ts +5 -0
  31. package/dist/assembly/render-target-host.d.ts.map +1 -1
  32. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  33. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  34. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  35. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  36. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  37. package/dist/assembly/renderer-inspection.d.ts +11 -0
  38. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  41. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  42. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +1 -1
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  46. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  47. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  48. package/dist/assembly/webgpu-renderer.d.ts +2 -1
  49. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  50. package/dist/authoring.mjs +2 -4
  51. package/dist/authoring.mjs.map +1 -1
  52. package/dist/barrel-distortion.d.ts +47 -0
  53. package/dist/barrel-distortion.d.ts.map +1 -0
  54. package/dist/chunk-3XUBWRY2.mjs +1842 -0
  55. package/dist/chunk-3XUBWRY2.mjs.map +1 -0
  56. package/dist/{chunk-OO3DRYK7.mjs → chunk-G6HDNGY7.mjs} +2400 -1767
  57. package/dist/chunk-G6HDNGY7.mjs.map +1 -0
  58. package/dist/{chunk-ZDQWGQW7.mjs → chunk-LM5IE7GF.mjs} +4 -4
  59. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
  60. package/dist/{chunk-VOZWDM3L.mjs → chunk-LNIUIKQ7.mjs} +1514 -498
  61. package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
  62. package/dist/chunk-MXTWKZO4.mjs +3268 -0
  63. package/dist/chunk-MXTWKZO4.mjs.map +1 -0
  64. package/dist/chunk-MZ4C7EHF.mjs +6942 -0
  65. package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
  66. package/dist/chunk-RIPAEGI6.mjs +48 -0
  67. package/dist/chunk-RIPAEGI6.mjs.map +1 -0
  68. package/dist/{chunk-LEAXOMYJ.mjs → chunk-SGPUJW3F.mjs} +117 -5
  69. package/dist/chunk-SGPUJW3F.mjs.map +1 -0
  70. package/dist/{chunk-PA5DRJNI.mjs → chunk-X2KA6WHM.mjs} +29 -4
  71. package/dist/chunk-X2KA6WHM.mjs.map +1 -0
  72. package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
  73. package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
  74. package/dist/cloud/density.d.ts +55 -0
  75. package/dist/cloud/density.d.ts.map +1 -0
  76. package/dist/cloud/extract.d.ts +25 -0
  77. package/dist/cloud/extract.d.ts.map +1 -0
  78. package/dist/cloud/feature.d.ts +57 -0
  79. package/dist/cloud/feature.d.ts.map +1 -0
  80. package/dist/cloud/frame-context.d.ts +8 -0
  81. package/dist/cloud/frame-context.d.ts.map +1 -0
  82. package/dist/cloud/inspection.d.ts +59 -0
  83. package/dist/cloud/inspection.d.ts.map +1 -0
  84. package/dist/cloud/optics.d.ts +56 -0
  85. package/dist/cloud/optics.d.ts.map +1 -0
  86. package/dist/cloud/parameters.d.ts +73 -0
  87. package/dist/cloud/parameters.d.ts.map +1 -0
  88. package/dist/cloud/resources.d.ts +60 -0
  89. package/dist/cloud/resources.d.ts.map +1 -0
  90. package/dist/cloud/shadow.d.ts +42 -0
  91. package/dist/cloud/shadow.d.ts.map +1 -0
  92. package/dist/cloud/temporal.d.ts +74 -0
  93. package/dist/cloud/temporal.d.ts.map +1 -0
  94. package/dist/components/barrel-distortion.d.ts +13 -0
  95. package/dist/components/barrel-distortion.d.ts.map +1 -0
  96. package/dist/components/cloud-layer.d.ts +29 -0
  97. package/dist/components/cloud-layer.d.ts.map +1 -0
  98. package/dist/components/index.d.ts +2 -0
  99. package/dist/components/index.d.ts.map +1 -1
  100. package/dist/components/instances.d.ts +20 -6
  101. package/dist/components/instances.d.ts.map +1 -1
  102. package/dist/construct-renderer.d.ts +1 -1
  103. package/dist/construct-renderer.d.ts.map +1 -1
  104. package/dist/construct-renderer.mjs +8406 -5785
  105. package/dist/construct-renderer.mjs.map +1 -1
  106. package/dist/device/gpu-residency.d.ts +19 -19
  107. package/dist/device/gpu-residency.d.ts.map +1 -1
  108. package/dist/dynamic-geometry.d.ts +5 -1
  109. package/dist/dynamic-geometry.d.ts.map +1 -1
  110. package/dist/errors/cloud.d.ts +59 -0
  111. package/dist/errors/cloud.d.ts.map +1 -0
  112. package/dist/errors/render.d.ts +20 -5
  113. package/dist/errors/render.d.ts.map +1 -1
  114. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  115. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  116. package/dist/extract/camera.d.ts.map +1 -1
  117. package/dist/extract/contracts.d.ts +5 -1
  118. package/dist/extract/contracts.d.ts.map +1 -1
  119. package/dist/extract/material-context.d.ts +7 -0
  120. package/dist/extract/material-context.d.ts.map +1 -0
  121. package/dist/features/barrel-distortion.d.ts +29 -0
  122. package/dist/features/barrel-distortion.d.ts.map +1 -0
  123. package/dist/features/error-reporting.d.ts +6 -2
  124. package/dist/features/error-reporting.d.ts.map +1 -1
  125. package/dist/features/host.d.ts +15 -0
  126. package/dist/features/host.d.ts.map +1 -1
  127. package/dist/features/plan.d.ts +10 -0
  128. package/dist/features/plan.d.ts.map +1 -1
  129. package/dist/features/render-graph-contribution.d.ts +5 -0
  130. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  131. package/dist/features/render-graph-raster.d.ts +1 -0
  132. package/dist/features/render-graph-raster.d.ts.map +1 -1
  133. package/dist/features/targets.d.ts +2 -0
  134. package/dist/features/targets.d.ts.map +1 -1
  135. package/dist/features/types.d.ts +48 -0
  136. package/dist/features/types.d.ts.map +1 -1
  137. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  138. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  139. package/dist/glyph-text-layout-system.d.ts +1 -1
  140. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  141. package/dist/gpu-dirty-ranges.d.ts +11 -0
  142. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  143. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  144. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  145. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  146. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  147. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  148. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  149. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  150. package/dist/gpu-driven/production-raster.d.ts +47 -3
  151. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  152. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  153. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  154. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  155. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  156. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  157. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  158. package/dist/gpu-scene.d.ts +5 -0
  159. package/dist/gpu-scene.d.ts.map +1 -1
  160. package/dist/hdrp-buffers.d.ts +2 -2
  161. package/dist/hdrp-buffers.d.ts.map +1 -1
  162. package/dist/ibl/frame-resources.d.ts.map +1 -1
  163. package/dist/ibl/skylight-bind-group.d.ts +14 -5
  164. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  165. package/dist/index.d.ts +30 -7
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.mjs +780 -9
  168. package/dist/index.mjs.map +1 -1
  169. package/dist/inspection-types.d.ts +135 -1
  170. package/dist/inspection-types.d.ts.map +1 -1
  171. package/dist/instance-buffer-cache.d.ts +4 -4
  172. package/dist/instance-buffer-cache.d.ts.map +1 -1
  173. package/dist/instances.d.ts +47 -100
  174. package/dist/instances.d.ts.map +1 -1
  175. package/dist/internal.mjs +7 -8
  176. package/dist/internal.mjs.map +1 -1
  177. package/dist/pbr-pipeline.d.ts +22 -4
  178. package/dist/pbr-pipeline.d.ts.map +1 -1
  179. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  180. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  181. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  182. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  183. package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
  184. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
  185. package/dist/pipeline/standard-output/resources.d.ts +2 -2
  186. package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
  187. package/dist/pipeline/standard-output/types.d.ts +4 -2
  188. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  189. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  190. package/dist/pipeline/standard-post.d.ts.map +1 -1
  191. package/dist/pipeline-builder.d.ts +1 -1
  192. package/dist/pipeline-builder.d.ts.map +1 -1
  193. package/dist/plugin.d.ts.map +1 -1
  194. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  195. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  196. package/dist/publication/contract.d.ts +77 -0
  197. package/dist/publication/contract.d.ts.map +1 -0
  198. package/dist/publication/dependencies.d.ts +7 -0
  199. package/dist/publication/dependencies.d.ts.map +1 -0
  200. package/dist/publication/prepare-geometry.d.ts +9 -0
  201. package/dist/publication/prepare-geometry.d.ts.map +1 -0
  202. package/dist/publication/programs.d.ts +5 -0
  203. package/dist/publication/programs.d.ts.map +1 -0
  204. package/dist/publication/publisher.d.ts +33 -0
  205. package/dist/publication/publisher.d.ts.map +1 -0
  206. package/dist/publication/receiver.d.ts +29 -0
  207. package/dist/publication/receiver.d.ts.map +1 -0
  208. package/dist/publication/resource-scope.d.ts +18 -0
  209. package/dist/publication/resource-scope.d.ts.map +1 -0
  210. package/dist/publication/targets.d.ts +33 -0
  211. package/dist/publication/targets.d.ts.map +1 -0
  212. package/dist/publication/video.d.ts +5 -0
  213. package/dist/publication/video.d.ts.map +1 -0
  214. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  215. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  216. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  218. package/dist/record/fold-buckets.d.ts +95 -0
  219. package/dist/record/fold-buckets.d.ts.map +1 -0
  220. package/dist/record/fold-instance-buffer.d.ts +6 -0
  221. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  222. package/dist/record/frame-lighting.d.ts +1 -0
  223. package/dist/record/frame-lighting.d.ts.map +1 -1
  224. package/dist/record/frame-snapshot.d.ts +43 -9
  225. package/dist/record/frame-snapshot.d.ts.map +1 -1
  226. package/dist/record/frame.d.ts +15 -65
  227. package/dist/record/frame.d.ts.map +1 -1
  228. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  229. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  230. package/dist/record/gpu-timing.d.ts +8 -0
  231. package/dist/record/gpu-timing.d.ts.map +1 -1
  232. package/dist/record/helpers.d.ts +2 -2
  233. package/dist/record/helpers.d.ts.map +1 -1
  234. package/dist/record/main-pass-geometry.d.ts +22 -6
  235. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  236. package/dist/record/main-pass-material.d.ts +14 -10
  237. package/dist/record/main-pass-material.d.ts.map +1 -1
  238. package/dist/record/main-pass-sprite-draws.d.ts +3 -16
  239. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  240. package/dist/record/main-pass.d.ts +13 -2
  241. package/dist/record/main-pass.d.ts.map +1 -1
  242. package/dist/record/motion-blur-receipt.d.ts +11 -0
  243. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  244. package/dist/record/prepared-material-bindings.d.ts +3 -3
  245. package/dist/record/prepared-material-bindings.d.ts.map +1 -1
  246. package/dist/record/probe-blend-buffer.d.ts +16 -0
  247. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  248. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  249. package/dist/record/render-context.d.ts +24 -5
  250. package/dist/record/render-context.d.ts.map +1 -1
  251. package/dist/record/shadow-pass.d.ts +2 -0
  252. package/dist/record/shadow-pass.d.ts.map +1 -1
  253. package/dist/record/skybox-post-pass.d.ts +1 -1
  254. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  255. package/dist/record/sprite-instance-buffer.d.ts +31 -0
  256. package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
  257. package/dist/record/target-capture-graph.d.ts +19 -0
  258. package/dist/record/target-capture-graph.d.ts.map +1 -0
  259. package/dist/record/typed-frame-graph.d.ts +24 -15
  260. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  261. package/dist/record/view-ubo.d.ts +11 -3
  262. package/dist/record/view-ubo.d.ts.map +1 -1
  263. package/dist/record/volume-params.d.ts +9 -0
  264. package/dist/record/volume-params.d.ts.map +1 -0
  265. package/dist/recovery/render-system-candidate.d.ts +14 -4
  266. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  267. package/dist/reflection/record-owner.d.ts.map +1 -1
  268. package/dist/render-contract.d.ts +46 -5
  269. package/dist/render-contract.d.ts.map +1 -1
  270. package/dist/render-graph-primitives.d.ts.map +1 -1
  271. package/dist/render-pipeline.d.ts +103 -2
  272. package/dist/render-pipeline.d.ts.map +1 -1
  273. package/dist/render-system-extract-tail.d.ts +3 -2
  274. package/dist/render-system-extract-tail.d.ts.map +1 -1
  275. package/dist/render-system-extract.d.ts +18 -9
  276. package/dist/render-system-extract.d.ts.map +1 -1
  277. package/dist/render-system-presentation.d.ts +23 -0
  278. package/dist/render-system-presentation.d.ts.map +1 -0
  279. package/dist/render-system-producer-roots.d.ts +10 -0
  280. package/dist/render-system-producer-roots.d.ts.map +1 -0
  281. package/dist/render-system-projections.d.ts +3 -2
  282. package/dist/render-system-projections.d.ts.map +1 -1
  283. package/dist/render-system-residency.d.ts +12 -0
  284. package/dist/render-system-residency.d.ts.map +1 -0
  285. package/dist/render-system.d.ts +22 -21
  286. package/dist/render-system.d.ts.map +1 -1
  287. package/dist/scene/probe-blend.d.ts +27 -0
  288. package/dist/scene/probe-blend.d.ts.map +1 -1
  289. package/dist/scene/render-scene.d.ts +18 -7
  290. package/dist/scene/render-scene.d.ts.map +1 -1
  291. package/dist/scene/render-source.d.ts +42 -0
  292. package/dist/scene/render-source.d.ts.map +1 -0
  293. package/dist/scene/source-systems.d.ts +6 -0
  294. package/dist/scene/source-systems.d.ts.map +1 -0
  295. package/dist/ssao-buffers.d.ts +9 -0
  296. package/dist/ssao-buffers.d.ts.map +1 -1
  297. package/dist/surface/dynamic-input.d.ts +133 -0
  298. package/dist/surface/dynamic-input.d.ts.map +1 -0
  299. package/dist/surface/gpu-driven.d.ts +41 -0
  300. package/dist/surface/gpu-driven.d.ts.map +1 -0
  301. package/dist/surface/submission-observation.d.ts +136 -0
  302. package/dist/surface/submission-observation.d.ts.map +1 -0
  303. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  304. package/dist/systems/skin-palette-types.d.ts +10 -0
  305. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  306. package/dist/systems/transparent-dispatch.d.ts +2 -2
  307. package/dist/systems/transparent-dispatch.d.ts.map +1 -1
  308. package/dist/systems/transparent-sort-config.d.ts +2 -1
  309. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  310. package/dist/temporal/gpu.d.ts +13 -1
  311. package/dist/temporal/gpu.d.ts.map +1 -1
  312. package/dist/temporal/index.mjs +6 -7
  313. package/dist/temporal/inspection.d.ts.map +1 -1
  314. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  315. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  316. package/dist/transmission/single-layer-medium.d.ts +89 -0
  317. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  318. package/dist/typed-render-graph-primitives.d.ts +14 -2
  319. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  320. package/dist/volume/component.d.ts +9 -4
  321. package/dist/volume/component.d.ts.map +1 -1
  322. package/dist/volume/extract.d.ts +1 -1
  323. package/dist/volume/extract.d.ts.map +1 -1
  324. package/dist/volume/inspection.d.ts +2 -0
  325. package/dist/volume/inspection.d.ts.map +1 -1
  326. package/dist/volume/passes.d.ts +4 -1
  327. package/dist/volume/passes.d.ts.map +1 -1
  328. package/dist/volume/resources.d.ts.map +1 -1
  329. package/package.json +22 -21
  330. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  331. package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
  332. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  333. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  334. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  335. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  336. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  337. package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
  338. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  339. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  340. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  341. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +5 -6
  348. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  349. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  350. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  351. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  352. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  353. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  354. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  355. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  356. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  357. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  358. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  359. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  360. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  361. package/src/__tests__/instances-store.unit.test.ts +97 -305
  362. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  363. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
  364. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +145 -0
  365. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  366. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  367. package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
  368. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  369. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  370. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  371. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  372. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  373. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  374. package/src/__tests__/physical-clearcoat.integration.test.ts +66 -8
  375. package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
  376. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  377. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  378. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  379. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  380. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  381. package/src/__tests__/render-error-code-owner.test-d.ts +8 -0
  382. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  383. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  384. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  385. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  386. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  387. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  388. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  389. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  390. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  391. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  392. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -8
  393. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  394. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  395. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  396. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  397. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  398. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  399. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  400. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  401. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  402. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  403. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  404. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  405. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  406. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  407. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  408. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  409. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  410. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  411. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  412. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  413. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  414. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  415. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  416. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  417. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  418. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  419. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  420. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  421. package/src/assembly/backend-contract.ts +30 -0
  422. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  423. package/src/assembly/canvas-draw-guard.ts +11 -0
  424. package/src/assembly/cloud-shadow-entry.ts +22 -0
  425. package/src/assembly/device-feature-admission.ts +2 -2
  426. package/src/assembly/dynamic-geometry-host.ts +65 -37
  427. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  428. package/src/assembly/factory.ts +2 -30
  429. package/src/assembly/host-contract.ts +8 -5
  430. package/src/assembly/material/assembly.ts +25 -13
  431. package/src/assembly/material/pipeline-helpers.ts +53 -12
  432. package/src/assembly/material-shader-policy.ts +55 -0
  433. package/src/assembly/material-shader-prewarm.ts +21 -10
  434. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  435. package/src/assembly/recovery/renderer-recover.ts +50 -18
  436. package/src/assembly/render-feature-post-processes.ts +54 -0
  437. package/src/assembly/render-target-host.ts +57 -47
  438. package/src/assembly/renderer-facade.ts +7 -2
  439. package/src/assembly/renderer-feature-inspection.ts +8 -2
  440. package/src/assembly/renderer-frame-transaction.ts +23 -0
  441. package/src/assembly/renderer-inspection.ts +28 -0
  442. package/src/assembly/skin-palette-owner.ts +1 -1
  443. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  444. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  445. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  446. package/src/assembly/webgpu-ready.ts +116 -62
  447. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  448. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  449. package/src/assembly/webgpu-renderer.ts +303 -313
  450. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  451. package/src/barrel-distortion.ts +247 -0
  452. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  453. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  454. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  455. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  456. package/src/cloud/density.ts +600 -0
  457. package/src/cloud/extract.ts +110 -0
  458. package/src/cloud/feature.ts +1810 -0
  459. package/src/cloud/frame-context.ts +42 -0
  460. package/src/cloud/inspection.ts +130 -0
  461. package/src/cloud/optics.ts +285 -0
  462. package/src/cloud/parameters.ts +255 -0
  463. package/src/cloud/resources.ts +122 -0
  464. package/src/cloud/shadow.ts +167 -0
  465. package/src/cloud/temporal.ts +226 -0
  466. package/src/components/barrel-distortion.ts +46 -0
  467. package/src/components/cloud-layer.ts +47 -0
  468. package/src/components/index.ts +2 -0
  469. package/src/components/instances.ts +18 -45
  470. package/src/components/sprite-instances.ts +1 -1
  471. package/src/construct-renderer.ts +1 -1
  472. package/src/device/gpu-residency.ts +26 -25
  473. package/src/dynamic-geometry.ts +12 -1
  474. package/src/errors/cloud.ts +103 -0
  475. package/src/errors/render.ts +47 -8
  476. package/src/examples/single-layer-medium-surface.ts +59 -0
  477. package/src/extract/camera.ts +15 -1
  478. package/src/extract/contracts.ts +5 -0
  479. package/src/extract/material-context.ts +21 -0
  480. package/src/features/barrel-distortion.ts +172 -0
  481. package/src/features/error-reporting.ts +26 -6
  482. package/src/features/host.ts +128 -19
  483. package/src/features/plan.ts +10 -0
  484. package/src/features/render-graph-contribution.ts +9 -0
  485. package/src/features/render-graph-raster.ts +45 -3
  486. package/src/features/targets.ts +66 -0
  487. package/src/features/types.ts +51 -0
  488. package/src/fullscreen-post-process-pass.ts +41 -9
  489. package/src/glyph-text-layout-system.ts +2 -2
  490. package/src/gpu-dirty-ranges.ts +48 -0
  491. package/src/gpu-driven/batch-topology.ts +53 -0
  492. package/src/gpu-driven/material-artifacts.ts +33 -25
  493. package/src/gpu-driven/prepared-draw.ts +12 -4
  494. package/src/gpu-driven/production-raster-material.ts +1894 -0
  495. package/src/gpu-driven/production-raster.ts +825 -784
  496. package/src/gpu-driven/resource-allocation.ts +142 -0
  497. package/src/gpu-driven/shadow-ownership.ts +71 -0
  498. package/src/gpu-driven/view-gpu.ts +164 -10
  499. package/src/gpu-scene.ts +75 -84
  500. package/src/hdrp-buffers.ts +4 -3
  501. package/src/ibl/frame-resources.ts +0 -1
  502. package/src/ibl/skylight-bind-group.ts +62 -32
  503. package/src/index.ts +205 -9
  504. package/src/inspection-types.ts +162 -0
  505. package/src/instance-buffer-cache.ts +4 -4
  506. package/src/instances.ts +152 -569
  507. package/src/pbr-pipeline.ts +230 -30
  508. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  509. package/src/pipeline/standard-forward-lane.ts +313 -57
  510. package/src/pipeline/standard-output/graph.ts +8 -2
  511. package/src/pipeline/standard-output/lut-gpu.ts +3 -3
  512. package/src/pipeline/standard-output/resources.ts +2 -2
  513. package/src/pipeline/standard-output/types.ts +12 -1
  514. package/src/pipeline/standard-pipeline.ts +291 -18
  515. package/src/pipeline/standard-post.ts +90 -24
  516. package/src/pipeline-builder.ts +1 -1
  517. package/src/plugin.ts +4 -0
  518. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  519. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  520. package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
  521. package/src/publication/__tests__/features.integration.test.ts +122 -0
  522. package/src/publication/__tests__/programs.unit.test.ts +25 -0
  523. package/src/publication/__tests__/publication.integration.test.ts +370 -0
  524. package/src/publication/__tests__/targets.integration.test.ts +120 -0
  525. package/src/publication/__tests__/video.browser.test.ts +50 -0
  526. package/src/publication/contract.ts +104 -0
  527. package/src/publication/dependencies.ts +54 -0
  528. package/src/publication/prepare-geometry.ts +94 -0
  529. package/src/publication/programs.ts +45 -0
  530. package/src/publication/publisher.ts +618 -0
  531. package/src/publication/receiver.ts +297 -0
  532. package/src/publication/resource-scope.ts +31 -0
  533. package/src/publication/targets.ts +182 -0
  534. package/src/publication/video.ts +33 -0
  535. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  536. package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
  537. package/src/record/__tests__/sprite-material-abi.unit.test.ts +9 -11
  538. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  539. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  540. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  541. package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
  542. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  543. package/src/record/barrel-distortion-frame.ts +110 -0
  544. package/src/record/dynamic-geometry-consumption.ts +39 -9
  545. package/src/record/fold-buckets.ts +855 -0
  546. package/src/record/fold-instance-buffer.ts +51 -0
  547. package/src/record/frame-lighting.ts +36 -2
  548. package/src/record/frame-snapshot.ts +45 -9
  549. package/src/record/frame.ts +258 -1105
  550. package/src/record/gpu-draw-receipts.ts +38 -0
  551. package/src/record/gpu-timing.ts +48 -5
  552. package/src/record/helpers.ts +2 -2
  553. package/src/record/main-pass-geometry.ts +272 -84
  554. package/src/record/main-pass-material.ts +102 -36
  555. package/src/record/main-pass-sprite-draws.ts +13 -217
  556. package/src/record/main-pass.ts +164 -27
  557. package/src/record/motion-blur-receipt.ts +91 -0
  558. package/src/record/prepared-material-bindings.ts +11 -6
  559. package/src/record/probe-blend-buffer.ts +180 -0
  560. package/src/record/recovery-pipeline.ts +35 -3
  561. package/src/record/render-context.ts +41 -5
  562. package/src/record/shadow-pass.ts +30 -4
  563. package/src/record/skybox-post-pass.ts +28 -4
  564. package/src/record/sprite-instance-buffer.ts +155 -0
  565. package/src/record/target-capture-graph.ts +258 -0
  566. package/src/record/typed-frame-graph.ts +776 -340
  567. package/src/record/view-ubo.ts +27 -4
  568. package/src/record/volume-params.ts +225 -0
  569. package/src/recovery/render-system-candidate.ts +243 -50
  570. package/src/reflection/record-owner.ts +7 -3
  571. package/src/render-contract.ts +54 -5
  572. package/src/render-graph-primitives.ts +7 -1
  573. package/src/render-pipeline.ts +130 -0
  574. package/src/render-system-extract-tail.ts +90 -78
  575. package/src/render-system-extract.ts +76 -76
  576. package/src/render-system-presentation.ts +56 -0
  577. package/src/render-system-producer-roots.ts +96 -0
  578. package/src/render-system-projections.ts +3 -2
  579. package/src/render-system-residency.ts +159 -0
  580. package/src/render-system.ts +421 -408
  581. package/src/scene/probe-blend.ts +96 -4
  582. package/src/scene/render-scene.ts +416 -337
  583. package/src/scene/render-source.ts +90 -0
  584. package/src/scene/source-systems.ts +33 -0
  585. package/src/ssao-buffers.ts +95 -2
  586. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  587. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  588. package/src/surface/dynamic-input.ts +658 -0
  589. package/src/surface/gpu-driven.ts +147 -0
  590. package/src/surface/submission-observation.ts +517 -0
  591. package/src/systems/skin-palette-allocator.ts +5 -1
  592. package/src/systems/skin-palette-types.ts +11 -0
  593. package/src/systems/transparent-dispatch.ts +2 -2
  594. package/src/systems/transparent-sort-config.ts +3 -1
  595. package/src/temporal/gpu.ts +101 -17
  596. package/src/temporal/inspection.ts +7 -1
  597. package/src/temporal/standard-scene-data.ts +5 -0
  598. package/src/temporal/target-coverage-attachment.ts +4 -0
  599. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  600. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  601. package/src/transmission/single-layer-medium.ts +322 -0
  602. package/src/typed-render-graph-primitives.ts +70 -2
  603. package/src/volume/component.ts +10 -9
  604. package/src/volume/extract.ts +11 -5
  605. package/src/volume/inspection.ts +3 -0
  606. package/src/volume/passes.ts +87 -4
  607. package/src/volume/resources.ts +2 -1
  608. package/dist/chunk-3RTCJTH4.mjs +0 -1610
  609. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  610. package/dist/chunk-BLXGONR2.mjs.map +0 -1
  611. package/dist/chunk-ILQ5MEZF.mjs +0 -32
  612. package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
  613. package/dist/chunk-LEAXOMYJ.mjs.map +0 -1
  614. package/dist/chunk-NB2S7ZRX.mjs +0 -1783
  615. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  616. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  617. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  618. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  619. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  620. package/dist/chunk-PLAXOOX5.mjs +0 -1907
  621. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  622. package/dist/chunk-RXZ3RGOU.mjs +0 -53
  623. package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
  624. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -1,16 +1,15 @@
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';
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';
1
+ import { DEFAULT_CLUSTER_GRID, DEFAULT_STANDARD_PROFILE, createIblKernelCache, STANDARD_PBR_UBO_SIZE, MATERIAL_PER_ENTITY_STRIDE, MAX_LIGHTS, CLUSTER_GRID_STRIDE_U32, LIGHT_INDEX_LIST_CAPACITY, createStandardClusterLayout } from './chunk-SGPUJW3F.mjs';
2
+ import { TRANSPARENT_SORT_MODE_LAYER_Z, TRANSPARENT_SORT_MODE_LAYER_Y, SPRITE_PREMULTIPLIED_ALPHA_BLEND } from './chunk-XSFB7XXQ.mjs';
3
+ import { probeBlendRecordOffset, PROBE_BLEND_RECORD_BYTE_SIZE, PROBE_BLEND_RECORD_STRIDE } from './chunk-RIPAEGI6.mjs';
4
+ import { GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, GPU_TEXTURE_USAGE_COPY_SRC, VertexColorVariantConflictError, GPU_SHADER_STAGE_COMPUTE, GPU_BUFFER_USAGE_STORAGE, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM, createHdrpBindGroupLayoutDescriptor, EquirectProjectionFailedError, SHADOW_ATLAS_DEFAULT_LAYERS, COOKIE_MATRIX_BYTES, SHADOW_ATLAS_DEFAULT_FACE_SIZE, ShadowAtlas, PointShadowAtlasUninitializedError, PointShadowAtlasBoundsViolationError, IES_SLICE_WIDTH, IES_SLICE_HEIGHT, COOKIE_SLICE_SIZE, StandardClusterTransportUnavailableError, GPU_SHADER_STAGE_VERTEX, GPU_SHADER_STAGE_FRAGMENT, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GPU_BUFFER_USAGE_INDEX, GPU_BUFFER_USAGE_VERTEX, isStandardPbrMaterialShader, worldEntityKey, instanceCollectionCacheKey, instanceUploadRangesForResident, createVisibilityBudget, GPU_BUFFER_USAGE_MAP_READ, getOpaqueResourceIdentity, pbrSkinMeshDynamicOffsets, gpuDrivenShadowDrawKey, SHADOW_CASTER_SHADER_ID, shadowCasterVariantSet, buildPbrMaterialUserRegionEntries, buildBindGroupLayoutDescriptor, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, GPU_BUFFER_USAGE_COPY_SRC, GPU_BUFFER_USAGE_INDIRECT, StandardLightBudgetExceededError, EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES, gpuDrivenSourceDrawItemIndex, matchPass, createPbrSkinMeshBindGroupEntries, physicalTextureFields, isCanonicalStandardPbrMaterialShader, RendererOperationError, resolveRenderTargetMaterialSource, VideoUploadUnsupportedError, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, StandardClusterIndexOverflowError, isStandardPbrSkinMaterialShader, SKIN_MATERIAL_SHADER_ID, FXAA_POST_PROCESS_ID, gpuDrivenDrawKey, materialBindGroupLayoutIdentity } from './chunk-MXTWKZO4.mjs';
6
5
  import { derive, ok, err as err$1, toShared, ASSET_ERROR_HINTS, deriveTextureLayout, handleSlot, resolveMaterialTextureCoordinates, KNOWN_PASS_KINDS } from '@forgeax/engine-types';
7
6
  import { RenderGraphError } from '@forgeax/engine-render-graph';
8
7
  import { ok as ok$1, err, RhiError } from '@forgeax/engine-rhi';
9
8
  import { mat3, vec3, mat4 } from '@forgeax/engine-math';
10
9
  import { deriveVertexLayoutProjection, DEFAULT_VERTEX_ATTRIBUTE_MAP, deriveVertexBufferLayout, deriveVertexBufferLayoutFromProjection } from '@forgeax/engine-geometry';
11
10
  import { resolveAssetHandle } from '@forgeax/engine-assets-runtime';
12
- import { probeVideoHighPerfUpload, VIDEO_ELEMENT_PROVIDER_KEY } from '@forgeax/engine-graphics-extras';
13
- import { DEFAULT_STANDARD_PBR_PARAM_SCHEMA, STANDARD_PIPELINE_PARAM_SCHEMA, GPU_DRIVEN_MATERIAL_ROW_BYTES, findVariantByKey, DEFAULT_MSDF_TEXT_PARAM_SCHEMA, DEFAULT_SPRITE_PARAM_SCHEMA, DEFAULT_UNLIT_PARAM_SCHEMA, STANDARD_PHYSICAL_TEXTURE_FIELDS, STANDARD_TEXTURE_MASK_OVERRIDE } from '@forgeax/engine-shader';
11
+ import { probeVideoHighPerfUpload, VIDEO_SOURCE_PROVIDER_KEY, videoSourceExtent } from '@forgeax/engine-graphics-extras';
12
+ import { STANDARD_PIPELINE_PARAM_SCHEMA, GPU_DRIVEN_MATERIAL_ROW_BYTES, findVariantByKey, DEFAULT_MSDF_TEXT_PARAM_SCHEMA, DEFAULT_SPRITE_PARAM_SCHEMA, DEFAULT_UNLIT_PARAM_SCHEMA, STANDARD_PHYSICAL_TEXTURE_FIELDS, STANDARD_TEXTURE_MASK_OVERRIDE } from '@forgeax/engine-shader';
14
13
  import { isCompressedFormat, bytesPerRow, blockParamsForFormat } from '@forgeax/engine-codec';
15
14
 
16
15
  // src/pipeline/render-extent.ts
@@ -119,6 +118,17 @@ function importRenderPipelineSurface(graph, topology) {
119
118
  }
120
119
  });
121
120
  }
121
+ function renderPipelineCloudHistoryTargets(input) {
122
+ const entries = [
123
+ ["cloud-history-radiance-previous", input.previousRadiance],
124
+ ["cloud-history-radiance-current", input.currentRadiance],
125
+ ["cloud-history-transmittance-previous", input.previousTransmittance],
126
+ ["cloud-history-transmittance-current", input.currentTransmittance],
127
+ ["cloud-history-depth-previous", input.previousDepth],
128
+ ["cloud-history-depth-current", input.currentDepth]
129
+ ];
130
+ return entries.map(([name, target]) => ({ name, kind: "scene-color", ...target }));
131
+ }
122
132
  var STORAGE_BUFFER_MIN_REQUIRED = 4;
123
133
  var BYTES_PER_DIRECT_LIGHT_SLOT = 80;
124
134
  var DirectLightSlotKind = {
@@ -1249,10 +1259,35 @@ function generateSsaoNoise(seed = 0) {
1249
1259
  var BYTES_PER_KERNEL_ELEMENT = 16;
1250
1260
  var UNIFORM_BYTES = 256;
1251
1261
  var fallbackCache = /* @__PURE__ */ new WeakMap();
1262
+ function destroyBuffer(runtime, device, buffer) {
1263
+ const destroyed = device.destroyBuffer(buffer);
1264
+ if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
1265
+ }
1266
+ function destroyTexture(runtime, device, texture) {
1267
+ const destroyed = device.destroyTexture(texture);
1268
+ if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
1269
+ }
1270
+ function retireSsaoResources(device, release) {
1271
+ const queue = device.queue;
1272
+ if (typeof queue.onSubmittedWorkDone === "function") {
1273
+ try {
1274
+ void queue.onSubmittedWorkDone().then(release, release);
1275
+ return;
1276
+ } catch {
1277
+ }
1278
+ }
1279
+ release();
1280
+ }
1281
+ function destroySsaoFallbackResources(runtime, resources) {
1282
+ destroyTexture(runtime, resources.device, resources.texture);
1283
+ }
1252
1284
  function getOrCreateSsaoFallbackTexture(runtime) {
1253
1285
  const cached = fallbackCache.get(runtime);
1254
1286
  if (cached !== void 0 && cached.device === runtime.device) return cached;
1255
- if (cached !== void 0) fallbackCache.delete(runtime);
1287
+ if (cached !== void 0) {
1288
+ fallbackCache.delete(runtime);
1289
+ retireSsaoResources(cached.device, () => destroySsaoFallbackResources(runtime, cached));
1290
+ }
1256
1291
  const device = runtime.device;
1257
1292
  const texRes = device.createTexture({
1258
1293
  label: "hdrp-ssao-fallback-white",
@@ -1281,6 +1316,7 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1281
1316
  );
1282
1317
  if (!writeRes.ok) {
1283
1318
  runtime.errorRegistry.fire(writeRes.error);
1319
+ destroyTexture(runtime, device, texRes.value);
1284
1320
  return null;
1285
1321
  }
1286
1322
  const viewRes = device.createTextureView(texRes.value, {
@@ -1295,6 +1331,7 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1295
1331
  });
1296
1332
  if (!viewRes.ok) {
1297
1333
  runtime.errorRegistry.fire(viewRes.error);
1334
+ destroyTexture(runtime, device, texRes.value);
1298
1335
  return null;
1299
1336
  }
1300
1337
  const samplerRes = device.createSampler({
@@ -1308,6 +1345,7 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1308
1345
  });
1309
1346
  if (!samplerRes.ok) {
1310
1347
  runtime.errorRegistry.fire(samplerRes.error);
1348
+ destroyTexture(runtime, device, texRes.value);
1311
1349
  return null;
1312
1350
  }
1313
1351
  const resources = {
@@ -1320,10 +1358,35 @@ function getOrCreateSsaoFallbackTexture(runtime) {
1320
1358
  return resources;
1321
1359
  }
1322
1360
  var cache = /* @__PURE__ */ new WeakMap();
1361
+ function destroySsaoBufferResources(runtime, buffers) {
1362
+ for (const buffer of [buffers.kernelBuffer, buffers.uniformBuffer]) {
1363
+ destroyBuffer(runtime, buffers.device, buffer);
1364
+ }
1365
+ destroyTexture(runtime, buffers.device, buffers.noiseTexture);
1366
+ }
1367
+ function destroyCreatedSsaoResources(runtime, device, buffers, textures) {
1368
+ for (const buffer of buffers) destroyBuffer(runtime, device, buffer);
1369
+ for (const texture of textures) destroyTexture(runtime, device, texture);
1370
+ }
1371
+ function resetSsaoResources(runtime) {
1372
+ const buffers = cache.get(runtime);
1373
+ if (buffers !== void 0) {
1374
+ cache.delete(runtime);
1375
+ retireSsaoResources(buffers.device, () => destroySsaoBufferResources(runtime, buffers));
1376
+ }
1377
+ const fallback = fallbackCache.get(runtime);
1378
+ if (fallback !== void 0) {
1379
+ fallbackCache.delete(runtime);
1380
+ retireSsaoResources(fallback.device, () => destroySsaoFallbackResources(runtime, fallback));
1381
+ }
1382
+ }
1323
1383
  function getOrCreateSsaoBuffers(runtime) {
1324
1384
  const cached = cache.get(runtime);
1325
1385
  if (cached !== void 0 && cached.device === runtime.device) return cached;
1326
- if (cached !== void 0) cache.delete(runtime);
1386
+ if (cached !== void 0) {
1387
+ cache.delete(runtime);
1388
+ retireSsaoResources(cached.device, () => destroySsaoBufferResources(runtime, cached));
1389
+ }
1327
1390
  const device = runtime.device;
1328
1391
  const kernelSamples = generateSsaoKernel();
1329
1392
  const kernelData = new Float32Array(SSAO_KERNEL_SAMPLE_COUNT * 4);
@@ -1347,6 +1410,7 @@ function getOrCreateSsaoBuffers(runtime) {
1347
1410
  const kernelWriteRes = device.queue.writeBuffer(kernelBufferRes.value, 0, kernelData);
1348
1411
  if (!kernelWriteRes.ok) {
1349
1412
  runtime.errorRegistry.fire(kernelWriteRes.error);
1413
+ destroyBuffer(runtime, device, kernelBufferRes.value);
1350
1414
  return null;
1351
1415
  }
1352
1416
  const noiseData = generateSsaoNoise();
@@ -1369,6 +1433,7 @@ function getOrCreateSsaoBuffers(runtime) {
1369
1433
  });
1370
1434
  if (!noiseTexRes.ok) {
1371
1435
  runtime.errorRegistry.fire(noiseTexRes.error);
1436
+ destroyBuffer(runtime, device, kernelBufferRes.value);
1372
1437
  return null;
1373
1438
  }
1374
1439
  const noiseCopyRes = device.queue.writeTexture(
@@ -1383,6 +1448,7 @@ function getOrCreateSsaoBuffers(runtime) {
1383
1448
  );
1384
1449
  if (!noiseCopyRes.ok) {
1385
1450
  runtime.errorRegistry.fire(noiseCopyRes.error);
1451
+ destroyCreatedSsaoResources(runtime, device, [kernelBufferRes.value], [noiseTexRes.value]);
1386
1452
  return null;
1387
1453
  }
1388
1454
  const uniformBufRes = device.createBuffer({
@@ -1393,6 +1459,7 @@ function getOrCreateSsaoBuffers(runtime) {
1393
1459
  });
1394
1460
  if (!uniformBufRes.ok) {
1395
1461
  runtime.errorRegistry.fire(uniformBufRes.error);
1462
+ destroyCreatedSsaoResources(runtime, device, [kernelBufferRes.value], [noiseTexRes.value]);
1396
1463
  return null;
1397
1464
  }
1398
1465
  const buffers = {
@@ -1689,7 +1756,7 @@ function createStandardSurfaceLightingBindGroup(runtime, layout, grid, ssaoOptio
1689
1756
  }
1690
1757
  return result.value;
1691
1758
  }
1692
- function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssaoOptions = { enabled: false }) {
1759
+ function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssaoOptions = { enabled: false }, meshBindingBytes = MESH_PER_ENTITY_STRIDE) {
1693
1760
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
1694
1761
  if (fallback === null) return null;
1695
1762
  const ssaoTexView = ssaoOptions.enabled ? ssaoOptions.ssaoBlurredView : fallback.view;
@@ -1705,7 +1772,7 @@ function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssa
1705
1772
  value: {
1706
1773
  buffer: meshStorageBuffer,
1707
1774
  offset: 0,
1708
- size: MESH_PER_ENTITY_STRIDE
1775
+ size: meshBindingBytes
1709
1776
  }
1710
1777
  }
1711
1778
  },
@@ -1718,17 +1785,16 @@ function createHdrpUnifiedBindGroup(runtime, hdrpBuffers, meshStorageBuffer, ssa
1718
1785
  }
1719
1786
  return result.value;
1720
1787
  }
1721
- function createHdrpSkinUnifiedBindGroup(runtime, hdrpBuffers, layout, meshStorageBuffer, paletteBuffer, paletteBindingWindowBytes, ssaoOptions = { enabled: false }) {
1788
+ function createHdrpSkinUnifiedBindGroup(runtime, hdrpBuffers, layout, meshStorageBuffer, paletteBuffer, paletteBindingWindowBytes, ssaoOptions = { enabled: false }, meshBindingBytes = MESH_PER_ENTITY_STRIDE) {
1722
1789
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
1723
1790
  if (fallback === null) return null;
1724
- const meshSize = MESH_PER_ENTITY_STRIDE;
1725
1791
  const result = runtime.device.createBindGroup({
1726
1792
  label: "hdrp-skin-unified-bg-group2",
1727
1793
  layout,
1728
1794
  entries: [
1729
1795
  ...createPbrSkinMeshBindGroupEntries(
1730
1796
  meshStorageBuffer,
1731
- meshSize,
1797
+ meshBindingBytes,
1732
1798
  paletteBuffer,
1733
1799
  paletteBindingWindowBytes
1734
1800
  ),
@@ -2445,7 +2511,7 @@ function computeProjectionMatrix(camera) {
2445
2511
  }
2446
2512
  return proj;
2447
2513
  }
2448
- var VIEW_UNIFORM_BYTES = 960;
2514
+ var VIEW_UNIFORM_BYTES = 1024;
2449
2515
  var POINTS_LINES_VIEW_BYTES = 160;
2450
2516
  var POINTS_LINES_VIEW_SLOT_STRIDE = 256;
2451
2517
  var POINTS_LINES_VIEW_SLOT_COUNT = 1024;
@@ -2453,7 +2519,7 @@ var POINTS_LINES_VIEW_BUFFER_SIZE = POINTS_LINES_VIEW_SLOT_STRIDE * POINTS_LINES
2453
2519
  var VIEW_UNIFORM_SLOT_STRIDE = 1024;
2454
2520
  var POINT_SHADOW_VIEW_SLOT_COUNT = 24;
2455
2521
  var CUBE_CAPTURE_VIEW_SLOT_BASE = 1 + POINT_SHADOW_VIEW_SLOT_COUNT;
2456
- var REFLECTION_PROBE_VIEW_SLOT_BASE = CUBE_CAPTURE_VIEW_SLOT_BASE + 6;
2522
+ var REFLECTION_PROBE_VIEW_SLOT_BASE = CUBE_CAPTURE_VIEW_SLOT_BASE + 6 + 1;
2457
2523
  var REFLECTION_PROBE_VIEW_SLOT_COUNT = 16;
2458
2524
  var VIEW_UNIFORM_BUFFER_SIZE = VIEW_UNIFORM_SLOT_STRIDE * (REFLECTION_PROBE_VIEW_SLOT_BASE + REFLECTION_PROBE_VIEW_SLOT_COUNT);
2459
2525
  function pointShadowViewOffset(layer, face) {
@@ -2509,7 +2575,7 @@ function writePointsLinesViewUbo(queue, buffer, camera, width, height, model, st
2509
2575
  const uploaded = queue.writeBuffer(buffer, byteOffset, payload);
2510
2576
  if (!uploaded.ok) throw uploaded.error;
2511
2577
  }
2512
- function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShadowSnapshots, temporalOrOffset, projectorSpotIndex) {
2578
+ function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShadowSnapshots, temporalOrOffset, projectorSpotIndex, cloudShadowProjection) {
2513
2579
  const byteOffset = typeof temporalOrOffset === "number" ? temporalOrOffset : 0;
2514
2580
  const resolvedTemporal = typeof temporalOrOffset === "number" ? void 0 : temporalOrOffset;
2515
2581
  const projMatrix = computeProjectionMatrix(camera);
@@ -2527,7 +2593,7 @@ function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShado
2527
2593
  }
2528
2594
  const mainProjection = mat4.create();
2529
2595
  mat4.multiply(mainProjection, jitteredProjection, viewMatrix);
2530
- const VIEW_PAYLOAD_FLOATS = 240;
2596
+ const VIEW_PAYLOAD_FLOATS = 256;
2531
2597
  const viewPayload = new Float32Array(VIEW_PAYLOAD_FLOATS);
2532
2598
  for (let i = 0; i < 16; i++) viewPayload[i] = mainProjection[i] ?? 0;
2533
2599
  viewPayload[16] = light.direction[0] ?? 0;
@@ -2576,6 +2642,20 @@ function writeViewUbo(queue, viewUniformBuffer, camera, light, lights, spotShado
2576
2642
  viewPayload[238] = ssr.maxRoughness;
2577
2643
  viewPayload[239] = 1;
2578
2644
  }
2645
+ if (cloudShadowProjection !== void 0) {
2646
+ viewPayload[240] = cloudShadowProjection.origin[0] ?? 0;
2647
+ viewPayload[241] = cloudShadowProjection.origin[1] ?? 0;
2648
+ viewPayload[242] = cloudShadowProjection.origin[2] ?? 0;
2649
+ viewPayload[244] = cloudShadowProjection.right[0] ?? 0;
2650
+ viewPayload[245] = cloudShadowProjection.right[1] ?? 0;
2651
+ viewPayload[246] = cloudShadowProjection.right[2] ?? 0;
2652
+ viewPayload[248] = cloudShadowProjection.up[0] ?? 0;
2653
+ viewPayload[249] = cloudShadowProjection.up[1] ?? 0;
2654
+ viewPayload[250] = cloudShadowProjection.up[2] ?? 0;
2655
+ viewPayload[252] = cloudShadowProjection.range;
2656
+ viewPayload[253] = cloudShadowProjection.lowSun ? 0 : 1;
2657
+ viewPayload[254] = cloudShadowProjection.lowSun ? 1 : 0;
2658
+ }
2579
2659
  if (lights.splitPlanes !== void 0) {
2580
2660
  for (let s = 0; s < 4; s++) {
2581
2661
  for (let lane = 0; lane < 4; lane++) {
@@ -2685,6 +2765,7 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2685
2765
  const b5View = atlasViewMaybe !== null ? atlasViewMaybe : pipelineState.shadowAtlasFallbackTextureView;
2686
2766
  const graphSpotShadowView = graphTargets?.spotShadow;
2687
2767
  const b8View = graphSpotShadowView !== void 0 ? graphSpotShadowView : pipelineState.shadowFallbackTextureView;
2768
+ const cloudShadowView = graphTargets?.cloudShadow ?? pipelineState.defaultWhiteTextureView;
2688
2769
  const extendedLighting = pipelineState.extendedLightingAvailable ?? true;
2689
2770
  const iesProfileTextureView = pipelineState.iesProfileTextureView;
2690
2771
  const cookieTextureView = pipelineState.cookieTextureView;
@@ -2716,6 +2797,7 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2716
2797
  extendedLightingResources.cookieMatrixBuffer
2717
2798
  ] : [];
2718
2799
  const projectorAvailable = pipelineState.projectorAvailable !== false;
2800
+ const lowLimitCloudBindings = !extendedLighting && !projectorAvailable;
2719
2801
  const b11View = graphTargets?.projector ?? pipelineState.defaultWhiteTextureView;
2720
2802
  const b12Sampler = graphTargets?.projectorSampler ?? pipelineState.defaultSampler;
2721
2803
  viewBindGroup = getOrCreateFromChain(
@@ -2729,7 +2811,8 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2729
2811
  b8View,
2730
2812
  ...extendedLightingViews,
2731
2813
  ...extendedLightingResources === void 0 && projectorAvailable ? [b11View, b12Sampler] : [],
2732
- pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer
2814
+ pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
2815
+ ...lowLimitCloudBindings ? [] : [cloudShadowView, pipelineState.defaultSampler]
2733
2816
  ],
2734
2817
  "view-main",
2735
2818
  () => {
@@ -2811,8 +2894,20 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2811
2894
  }
2812
2895
  },
2813
2896
  ...extendedLightingResources === void 0 && projectorAvailable ? [
2814
- { binding: 11, resource: { kind: "textureView", value: b11View } },
2815
- { binding: 12, resource: { kind: "sampler", value: b12Sampler } }
2897
+ {
2898
+ binding: 11,
2899
+ resource: {
2900
+ kind: "textureView",
2901
+ value: b11View
2902
+ }
2903
+ },
2904
+ {
2905
+ binding: 12,
2906
+ resource: {
2907
+ kind: "sampler",
2908
+ value: b12Sampler
2909
+ }
2910
+ }
2816
2911
  ] : [],
2817
2912
  ...extendedLightingResources !== void 0 ? [
2818
2913
  {
@@ -2860,7 +2955,23 @@ function buildPerFrameBindGroups(internals, frameState, pipelineState, hasValida
2860
2955
  }
2861
2956
  }
2862
2957
  }
2863
- ] : []
2958
+ ] : [],
2959
+ ...lowLimitCloudBindings ? [] : [
2960
+ {
2961
+ binding: 16,
2962
+ resource: {
2963
+ kind: "textureView",
2964
+ value: cloudShadowView
2965
+ }
2966
+ },
2967
+ {
2968
+ binding: 17,
2969
+ resource: {
2970
+ kind: "sampler",
2971
+ value: pipelineState.defaultSampler
2972
+ }
2973
+ }
2974
+ ]
2864
2975
  // feat-20260625-spot-light-shadow-mapping w25: the per-spot
2865
2976
  // fragment-read lightViewProj matrices fold into the View UBO
2866
2977
  // (binding 0, `view.spotLightViewProj`) — no standalone binding 9
@@ -4295,6 +4406,144 @@ var GpuTexture = class {
4295
4406
  return r;
4296
4407
  }
4297
4408
  };
4409
+
4410
+ // src/record/sprite-instance-buffer.ts
4411
+ function interleaveSpriteInstanceBuffer(transforms, regions, includePrevious = false) {
4412
+ const count = transforms.length / 16;
4413
+ const stride = includePrevious ? 36 : 20;
4414
+ const regionOffset = includePrevious ? 32 : 16;
4415
+ const out = new Float32Array(count * stride);
4416
+ for (let i = 0; i < count; i++) {
4417
+ const dstBase = i * stride;
4418
+ const transformBase = i * 16;
4419
+ const regionBase = i * 4;
4420
+ for (let k = 0; k < 16; k++) out[dstBase + k] = transforms[transformBase + k] ?? 0;
4421
+ if (includePrevious) {
4422
+ for (let k = 0; k < 16; k++) {
4423
+ out[dstBase + 16 + k] = transforms[transformBase + k] ?? 0;
4424
+ }
4425
+ }
4426
+ for (let k = 0; k < 4; k++) {
4427
+ out[dstBase + regionOffset + k] = regions[regionBase + k] ?? 0;
4428
+ }
4429
+ }
4430
+ return out;
4431
+ }
4432
+ function spriteInstancesCacheHit(entry, snapshot, requestedBytes) {
4433
+ return entry !== void 0 && entry.uploadedArchVersion === snapshot.archVersion && entry.uploadedByteLength === requestedBytes;
4434
+ }
4435
+ function resolveSpriteInstancesBuffer(c, spriteEntry, fallbackBuffer, fallbackCount) {
4436
+ const { runtime, frameState } = c;
4437
+ let buffer = fallbackBuffer;
4438
+ let count = fallbackCount;
4439
+ const spriteInstancesSnap = spriteEntry.source.spriteInstances;
4440
+ if (spriteInstancesSnap !== void 0) {
4441
+ if (spriteInstancesSnap.instanceCount === 0) return { buffer, count: 0 };
4442
+ const uniformFallback = runtime.device.caps.storageBuffer === false;
4443
+ const interleaved = interleaveSpriteInstanceBuffer(
4444
+ spriteInstancesSnap.transforms,
4445
+ spriteInstancesSnap.regions,
4446
+ !uniformFallback
4447
+ );
4448
+ const requestedBytes = interleaved.byteLength;
4449
+ const cap = runtime.device.limits.maxStorageBufferBindingSize;
4450
+ if (typeof cap === "number" && requestedBytes > cap) {
4451
+ runtime.errorRegistry.fire(
4452
+ new RhiError({
4453
+ code: "limit-exceeded",
4454
+ expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
4455
+ hint: "reduce SpriteInstances instance count to fit within device.limits.maxStorageBufferBindingSize (144 bytes per instance: current mat4 64B + previous mat4 64B + region 16B)",
4456
+ detail: {
4457
+ maxStorageBufferBindingSize: cap,
4458
+ requestedBytes
4459
+ }
4460
+ })
4461
+ );
4462
+ } else {
4463
+ const cachedSpriteInst = frameState.instanceBuffers.get(
4464
+ worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey)
4465
+ );
4466
+ let activeSpriteInst = null;
4467
+ if (spriteInstancesCacheHit(cachedSpriteInst, spriteInstancesSnap, requestedBytes)) {
4468
+ activeSpriteInst = cachedSpriteInst ?? null;
4469
+ } else if (requestedBytes > 0) {
4470
+ const bufRes = runtime.device.createBuffer({
4471
+ size: requestedBytes,
4472
+ usage: (uniformFallback ? GPU_BUFFER_USAGE_UNIFORM : GPU_BUFFER_USAGE_STORAGE) | GPU_BUFFER_USAGE_COPY_DST,
4473
+ mappedAtCreation: false
4474
+ });
4475
+ if (!bufRes.ok) {
4476
+ runtime.errorRegistry.fire(bufRes.error);
4477
+ } else {
4478
+ if (cachedSpriteInst !== void 0 && !cachedSpriteInst.buffer.isDestroyed) {
4479
+ const r = cachedSpriteInst.buffer.destroy();
4480
+ if (!r.ok) runtime.errorRegistry.fire(r.error);
4481
+ }
4482
+ const newBuf = new GpuBuffer(runtime.device, bufRes.value);
4483
+ activeSpriteInst = {
4484
+ buffer: newBuf,
4485
+ uploadedArchVersion: spriteInstancesSnap.archVersion,
4486
+ uploadedByteLength: requestedBytes
4487
+ };
4488
+ frameState.instanceBuffers.set(
4489
+ worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
4490
+ activeSpriteInst
4491
+ );
4492
+ }
4493
+ }
4494
+ if (activeSpriteInst !== null && requestedBytes > 0) {
4495
+ const writeRes = runtime.device.queue.writeBuffer(
4496
+ activeSpriteInst.buffer.handle,
4497
+ 0,
4498
+ interleaved
4499
+ );
4500
+ if (!writeRes.ok) {
4501
+ runtime.errorRegistry.fire(writeRes.error);
4502
+ } else {
4503
+ buffer = activeSpriteInst.buffer.handle;
4504
+ count = spriteInstancesSnap.instanceCount;
4505
+ }
4506
+ }
4507
+ }
4508
+ }
4509
+ return { buffer, count };
4510
+ }
4511
+
4512
+ // src/record/fold-instance-buffer.ts
4513
+ function resolveFoldInstanceBuffer(c, bucket, headIndex) {
4514
+ const { runtime, frameState } = c;
4515
+ const key = -1 - ((bucket.materialHandle & 65535) << 16 | headIndex & 65535);
4516
+ const uniform = runtime.device.caps.storageBuffer === false;
4517
+ const payload = uniform ? bucket.transforms : packInstanceStorageBuffer(bucket.transforms);
4518
+ let resident = frameState.instanceBuffers.get(key);
4519
+ if (resident === void 0 || resident.uploadedByteLength !== payload.byteLength) {
4520
+ const created = runtime.device.createBuffer({
4521
+ size: payload.byteLength,
4522
+ usage: (uniform ? GPU_BUFFER_USAGE_UNIFORM : GPU_BUFFER_USAGE_STORAGE) | GPU_BUFFER_USAGE_COPY_DST,
4523
+ mappedAtCreation: false
4524
+ });
4525
+ if (!created.ok) {
4526
+ runtime.errorRegistry.fire(created.error);
4527
+ return null;
4528
+ }
4529
+ if (resident !== void 0 && !resident.buffer.isDestroyed) {
4530
+ const destroyed = resident.buffer.destroy();
4531
+ if (!destroyed.ok) runtime.errorRegistry.fire(destroyed.error);
4532
+ }
4533
+ resident = {
4534
+ buffer: new GpuBuffer(runtime.device, created.value),
4535
+ uploadedArchVersion: bucket.bucketSize,
4536
+ uploadedByteLength: payload.byteLength
4537
+ };
4538
+ frameState.instanceBuffers.set(key, resident);
4539
+ }
4540
+ const written = runtime.device.queue.writeBuffer(resident.buffer.handle, 0, payload);
4541
+ if (!written.ok) {
4542
+ runtime.errorRegistry.fire(written.error);
4543
+ return null;
4544
+ }
4545
+ return resident.buffer.handle;
4546
+ }
4298
4547
  var STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES = 18;
4299
4548
  function isOrdinaryMaterialVariant(variant) {
4300
4549
  return variant.defines.COVERAGE_ONLY !== true;
@@ -4378,7 +4627,7 @@ var COMPRESSION_FEATURES = [
4378
4627
  function transmissionBackdropAvailable(limit) {
4379
4628
  return limit === void 0 || limit >= STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES;
4380
4629
  }
4381
- var STANDARD_PHYSICAL_REQUIRED_SAMPLED_TEXTURES = 22;
4630
+ var STANDARD_PHYSICAL_REQUIRED_SAMPLED_TEXTURES = 23;
4382
4631
  function deriveDeviceFeatureAdmission(adapter, options) {
4383
4632
  const requiredFeatures = COMPRESSION_FEATURES.filter((feature) => adapter.features.has(feature));
4384
4633
  const timestampRequested = options?.gpuPassTiming !== void 0 || options?.captureGpuTimings === true;
@@ -4403,7 +4652,7 @@ function deviceOptionsForAdapter(adapter, options) {
4403
4652
 
4404
4653
  // src/ibl/skylight-bind-group.ts
4405
4654
  var FALLBACK_BYTES_PER_ROW = 256;
4406
- function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmission, textureInjections = []) {
4655
+ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmission, textureInjections = [], surfaceMedium) {
4407
4656
  const iblStart = materialEntries.length;
4408
4657
  const result = [
4409
4658
  ...materialEntries,
@@ -4429,10 +4678,6 @@ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmis
4429
4678
  },
4430
4679
  {
4431
4680
  binding: iblStart + 5,
4432
- resource: { kind: "sampler", value: skylight.brdfLutSampler }
4433
- },
4434
- {
4435
- binding: iblStart + 6,
4436
4681
  resource: { kind: "buffer", value: { buffer: skylight.intensityBuffer } }
4437
4682
  }
4438
4683
  ];
@@ -4450,6 +4695,35 @@ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmis
4450
4695
  resource: { kind: "textureView", value: transmissionView }
4451
4696
  }
4452
4697
  );
4698
+ if (surfaceMedium !== void 0) {
4699
+ const surfaceStart = result.length;
4700
+ result.push(
4701
+ {
4702
+ binding: surfaceStart,
4703
+ resource: { kind: "sampler", value: surfaceMedium.rawDepthSampler }
4704
+ },
4705
+ {
4706
+ binding: surfaceStart + 1,
4707
+ resource: { kind: "textureView", value: surfaceMedium.rawDepthView }
4708
+ },
4709
+ {
4710
+ binding: surfaceStart + 2,
4711
+ resource: { kind: "sampler", value: surfaceMedium.nearestLayerSampler }
4712
+ },
4713
+ {
4714
+ binding: surfaceStart + 3,
4715
+ resource: { kind: "textureView", value: surfaceMedium.nearestLayerView }
4716
+ },
4717
+ {
4718
+ binding: surfaceStart + 4,
4719
+ resource: { kind: "sampler", value: surfaceMedium.nearestDepthSampler }
4720
+ },
4721
+ {
4722
+ binding: surfaceStart + 5,
4723
+ resource: { kind: "textureView", value: surfaceMedium.nearestDepthView }
4724
+ }
4725
+ );
4726
+ }
4453
4727
  const physicalStart = 26;
4454
4728
  for (let index = 0; index < textureInjections.length; index += 1) {
4455
4729
  const resource = textureInjections[index];
@@ -4466,13 +4740,15 @@ function assembleMaterialWithSkylightEntries(materialEntries, skylight, transmis
4466
4740
  }
4467
4741
  );
4468
4742
  }
4469
- result.push({
4470
- binding: 47,
4471
- resource: {
4472
- kind: "textureView",
4473
- value: skylight.skylightPrefilterView ?? skylight.prefilterView
4474
- }
4475
- });
4743
+ if (surfaceMedium === void 0) {
4744
+ result.push({
4745
+ binding: 47,
4746
+ resource: {
4747
+ kind: "textureView",
4748
+ value: skylight.skylightPrefilterView ?? skylight.prefilterView
4749
+ }
4750
+ });
4751
+ }
4476
4752
  return result;
4477
4753
  }
4478
4754
  function createSkylightFallback(device, queue) {
@@ -4736,116 +5012,6 @@ function deriveRenderDataCubemap(source) {
4736
5012
  cubeUsage: GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING | GPU_TEXTURE_USAGE_COPY_DST | GPU_TEXTURE_USAGE_COPY_SRC
4737
5013
  });
4738
5014
  }
4739
- var STANDARD_PBR_UBO_SIZE = derive(DEFAULT_STANDARD_PBR_PARAM_SCHEMA).uboLayout.totalBytes;
4740
- var MATERIAL_PER_ENTITY_STRIDE = Math.ceil(STANDARD_PBR_UBO_SIZE / 256) * 256;
4741
- function resolveSurfaceProfile(storageFormat, viewFormat, facts) {
4742
- if (facts.surfaceViewFormats) {
4743
- return ok$1({
4744
- kind: "dual-view",
4745
- storageFormat,
4746
- viewFormat,
4747
- viewFormats: [viewFormat],
4748
- hasDisplayEndpoint: true
4749
- });
4750
- }
4751
- if (!facts.rawAttachment || !facts.floatRenderAttachment) {
4752
- return err(
4753
- new RhiError({
4754
- code: "webgpu-runtime-error",
4755
- expected: "raw surface attachment and rgba16float render attachment capabilities",
4756
- hint: "surface profile cannot establish a raw-only linear output route",
4757
- detail: {
4758
- error: {
4759
- code: "surface-raw-endpoint-failed",
4760
- message: "raw-only surface capabilities are incomplete"
4761
- }
4762
- }
4763
- })
4764
- );
4765
- }
4766
- return ok$1({
4767
- kind: "raw-only",
4768
- storageFormat,
4769
- viewFormat: storageFormat,
4770
- viewFormats: [],
4771
- hasDisplayEndpoint: false
4772
- });
4773
- }
4774
- function resolveSurfaceFormatPair(_backendKind, storage, view) {
4775
- return { storage, view };
4776
- }
4777
- function surfaceCapabilityFacts(device, storageFormat) {
4778
- const internal = device;
4779
- return {
4780
- surfaceViewFormats: internal.surfaceViewFormats ?? device.caps?.backendKind !== "wgpu-webgl2",
4781
- rawAttachment: storageFormat === "rgba8unorm" || storageFormat === "bgra8unorm",
4782
- floatRenderAttachment: device.caps?.rgba16floatRenderable ?? true
4783
- };
4784
- }
4785
- function configureSurface(context, device, format, colorAttachmentFormat) {
4786
- const backendKind = device.caps?.backendKind ?? "webgpu";
4787
- const isWebGl2 = backendKind === "wgpu-webgl2";
4788
- const surfaceFormats = resolveSurfaceFormatPair(
4789
- backendKind,
4790
- format,
4791
- colorAttachmentFormat
4792
- );
4793
- const profile = resolveSurfaceProfile(
4794
- surfaceFormats.storage,
4795
- surfaceFormats.view,
4796
- surfaceCapabilityFacts(device, surfaceFormats.storage)
4797
- );
4798
- if (!profile.ok) return profile;
4799
- const supportsTextureBinding = backendKind !== "wgpu-webgl2" && (device.caps?.storageBuffer ?? true);
4800
- const configured = context.configure({
4801
- device,
4802
- format: surfaceFormats.storage,
4803
- alphaMode: isWebGl2 ? "opaque" : "premultiplied",
4804
- usage: GPU_TEXTURE_USAGE_RENDER_ATTACHMENT | (supportsTextureBinding ? GPU_TEXTURE_USAGE_TEXTURE_BINDING : 0) | (isWebGl2 ? 0 : GPU_TEXTURE_USAGE_COPY_SRC),
4805
- viewFormats: [...profile.value.viewFormats]
4806
- });
4807
- if (!configured.ok) return configured;
4808
- if (isWebGl2 && (context.presentationProof === void 0 || !context.presentationProof.descriptor || !context.presentationProof.acquisition || !context.presentationProof.validation || typeof context.presentationProof.surfaceIdentity !== "string" || context.presentationProof.surfaceIdentity.length === 0 || context.presentationProof.requested === void 0 || context.presentationProof.validated === void 0 || JSON.stringify(context.presentationProof.requested) !== JSON.stringify(context.presentationProof.validated))) {
4809
- return err(
4810
- new RhiError({
4811
- code: "webgpu-runtime-error",
4812
- expected: "WebGL2 surface storage has descriptor, acquisition, and validation proof",
4813
- hint: "run the concrete presentation probe and retain the last-known-good graph when proof is absent",
4814
- detail: {
4815
- error: {
4816
- code: "surface-raw-endpoint-failed",
4817
- message: "surface storage raw endpoint proof is incomplete"
4818
- }
4819
- }
4820
- })
4821
- );
4822
- }
4823
- return ok$1(void 0);
4824
- }
4825
- function selectSwapChainFormat(storageBufferCapable, surfaceViewFormats = true) {
4826
- if (!storageBufferCapable) {
4827
- return {
4828
- storage: "rgba8unorm",
4829
- view: surfaceViewFormats ? "rgba8unorm-srgb" : "rgba8unorm"
4830
- };
4831
- }
4832
- const nav = globalThis.navigator;
4833
- const gpu = nav?.gpu;
4834
- const getPreferred = gpu?.getPreferredCanvasFormat;
4835
- if (gpu !== void 0 && typeof getPreferred === "function") {
4836
- const storage = getPreferred.call(gpu);
4837
- const view = storage === "rgba8unorm" ? "rgba8unorm-srgb" : storage === "bgra8unorm" ? "bgra8unorm-srgb" : storage;
4838
- return {
4839
- storage,
4840
- view: surfaceViewFormats ? view : storage
4841
- };
4842
- }
4843
- return {
4844
- storage: "rgba8unorm",
4845
- view: surfaceViewFormats ? "rgba8unorm-srgb" : "rgba8unorm",
4846
- fallbackReason: "preferred-canvas-format-missing"
4847
- };
4848
- }
4849
5015
 
4850
5016
  // src/record/main-pass-material.ts
4851
5017
  function selectMaterialGroup2(clusterGroup, meshGroup, group2Contract) {
@@ -4984,8 +5150,8 @@ function clearVideoUploadFailureEpisode(store, entityKey, clip) {
4984
5150
  }
4985
5151
  function videoTextureView(world, store, runtime, entityKey, clip, highPerfAvailable) {
4986
5152
  if (store === void 0) return void 0;
4987
- const provider = world.hasResource(VIDEO_ELEMENT_PROVIDER_KEY) ? world.getResource(VIDEO_ELEMENT_PROVIDER_KEY) : void 0;
4988
- const element = provider?.getElement(entityKey, clip);
5153
+ const provider = !("resolveAsset" in world) && world.hasResource(VIDEO_SOURCE_PROVIDER_KEY) ? world.getResource(VIDEO_SOURCE_PROVIDER_KEY) : void 0;
5154
+ const element = "resolveAsset" in world ? world.videoFrame(entityKey, clip) : provider?.getSource(entityKey, clip);
4989
5155
  if (element === void 0 && !highPerfAvailable) {
4990
5156
  if (markVideoUploadFailureEpisode(store, entityKey, clip)) {
4991
5157
  runtime.errorRegistry.fire(new VideoUploadUnsupportedError());
@@ -4996,9 +5162,9 @@ function videoTextureView(world, store, runtime, entityKey, clip, highPerfAvaila
4996
5162
  clearVideoUploadFailureEpisode(store, entityKey, clip);
4997
5163
  return store.getView(clip);
4998
5164
  }
4999
- const width = element.videoWidth;
5000
- const height = element.videoHeight;
5001
- if (width <= 0 || height <= 0 || element.readyState < 2) return store.getView(clip);
5165
+ const extent = videoSourceExtent(element);
5166
+ if (extent === void 0) return store.getView(clip);
5167
+ const { width, height } = extent;
5002
5168
  const uploaded = store.uploadFrame(clip, element, width, height);
5003
5169
  if (uploaded === void 0) return store.getView(clip);
5004
5170
  if (!uploaded.ok) {
@@ -5252,7 +5418,7 @@ function recordIblMaterialBinding(frameState, materialBgl, bindGroup, entries, i
5252
5418
  if (receipt === void 0) return;
5253
5419
  const skylightBindingStart = entries.findIndex((entry) => entry.binding === iblStart);
5254
5420
  if (skylightBindingStart < 0) return;
5255
- const iblEntries = entries.slice(skylightBindingStart, skylightBindingStart + 7);
5421
+ const iblEntries = entries.slice(skylightBindingStart, skylightBindingStart + 6);
5256
5422
  const projected = [];
5257
5423
  for (const entry of iblEntries) {
5258
5424
  if (entry.resource.kind === "externalTexture") continue;
@@ -5277,9 +5443,10 @@ function recordIblMaterialBinding(frameState, materialBgl, bindGroup, entries, i
5277
5443
  errors: []
5278
5444
  };
5279
5445
  }
5280
- function isMaterialBgAssemblyCacheHit(cached, material, materialBgl, materialBuffer, skylightResources, materialResourceEpoch, transmissionBackdropView, sceneMaterialBuffer) {
5281
- if (transmissionBackdropView != null) return false;
5282
- 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;
5446
+ function isMaterialBgAssemblyCacheHit(cached, material, materialBgl, materialBuffer, skylightResources, materialResourceEpoch, transmissionBackdropView, sceneMaterialBuffer, surfaceRawDepthView) {
5447
+ if (transmissionBackdropView != null || surfaceRawDepthView != null || (material.textureSources?.size ?? 0) > 0)
5448
+ return false;
5449
+ 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.intensityBuffer === skylightResources.intensityBuffer;
5283
5450
  }
5284
5451
  function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWorld = deps.world, materialShaderId = submeshMaterial.materialShaderId) {
5285
5452
  const {
@@ -5294,6 +5461,9 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5294
5461
  materialBgShared,
5295
5462
  materialBgAssemblyCache,
5296
5463
  transmissionBackdropView,
5464
+ surfaceRawDepthView,
5465
+ surfaceNearestLayerView,
5466
+ surfaceNearestDepthView,
5297
5467
  bindGroupCounts,
5298
5468
  frameState
5299
5469
  } = deps;
@@ -5303,6 +5473,35 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5303
5473
  const materialCacheKey = smMaterialHandle === void 0 ? void 0 : `${materialWorld.identity}:${smMaterialHandle}:${materialShaderId ?? ""}:${selectedProbe?.probeIndex ?? "sky"}`;
5304
5474
  const smHasVideoFields = (submeshMaterial.videoTextureFields?.size ?? 0) > 0;
5305
5475
  const smShaderId = materialShaderId;
5476
+ const selectedMaterialShaderArtifact = smShaderId === void 0 ? void 0 : runtime.getMaterialShaderArtifact?.(smShaderId);
5477
+ const selectedMediumShader = smShaderId === "forgeax::single-layer-medium" || selectedMaterialShaderArtifact?.receipt?.surface?.model === "single-layer-medium";
5478
+ let surfaceMediumResources;
5479
+ if (selectedMediumShader) {
5480
+ if (surfaceRawDepthView == null) {
5481
+ throw new RhiError({
5482
+ code: "rhi-descriptor-invalid",
5483
+ expected: "single-layer medium material bind group has producer-owned raw depth",
5484
+ hint: "admit the Surface material only from a graph pass with an available raw-depth pair"
5485
+ });
5486
+ }
5487
+ const nearestLayerView = surfaceNearestLayerView ?? transmissionBackdropView;
5488
+ const nearestDepthView = surfaceNearestDepthView ?? pipelineState.shadowFallbackTextureView;
5489
+ if (nearestLayerView == null || pipelineState.surfaceMediumDepthSampler === void 0) {
5490
+ throw new RhiError({
5491
+ code: "rhi-descriptor-invalid",
5492
+ expected: "single-layer medium material bind group has paired nearest resources and depth sampler",
5493
+ hint: "publish the nearest-layer target and the non-filtering raw-depth sampler before recording the Surface pass"
5494
+ });
5495
+ }
5496
+ surfaceMediumResources = {
5497
+ rawDepthSampler: pipelineState.surfaceMediumDepthSampler,
5498
+ rawDepthView: surfaceRawDepthView,
5499
+ nearestLayerSampler: effectiveSkylightResources.prefilterSampler,
5500
+ nearestLayerView,
5501
+ nearestDepthSampler: pipelineState.surfaceMediumDepthSampler,
5502
+ nearestDepthView
5503
+ };
5504
+ }
5306
5505
  const smSchema = (smShaderId !== void 0 ? runtime.getParamSchema?.(smShaderId) : void 0) ?? submeshMaterial.materialParamSchema;
5307
5506
  const smPerShaderBgl = smShaderId !== void 0 ? runtime.getMaterialBindGroupLayout?.(smShaderId, smSchema) : void 0;
5308
5507
  const smMaterialBgl = smPerShaderBgl ?? pipelineState.materialBindGroupLayout;
@@ -5322,7 +5521,8 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5322
5521
  effectiveSkylightResources,
5323
5522
  store.materialResourceEpoch,
5324
5523
  transmissionBackdropView,
5325
- sceneMaterialBuffer
5524
+ sceneMaterialBuffer,
5525
+ surfaceRawDepthView
5326
5526
  )) {
5327
5527
  if (diagnosticsEnabled) {
5328
5528
  recordIblMaterialBinding(
@@ -5352,10 +5552,6 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5352
5552
  },
5353
5553
  {
5354
5554
  binding: 6 + smUserRegionFields.length * 2,
5355
- resource: { kind: "sampler", value: effectiveSkylightResources.brdfLutSampler }
5356
- },
5357
- {
5358
- binding: 7 + smUserRegionFields.length * 2,
5359
5555
  resource: {
5360
5556
  kind: "buffer",
5361
5557
  value: { buffer: effectiveSkylightResources.intensityBuffer }
@@ -5464,14 +5660,16 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5464
5660
  });
5465
5661
  }
5466
5662
  const transmissionSampler = transmissionBackdropView != null ? effectiveSkylightResources.prefilterSampler : pipelineState.defaultSampler;
5663
+ const keepMediumBackdropSlots = surfaceMediumResources !== void 0;
5467
5664
  const smMergedEntries = assembleMaterialWithSkylightEntries(
5468
5665
  smBaseEntries,
5469
5666
  effectiveSkylightResources,
5470
- transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage) ? {
5667
+ transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage) || keepMediumBackdropSlots ? {
5471
5668
  sampler: transmissionSampler,
5472
- ...transmissionBackdropView === void 0 ? {} : { backdropView: transmissionBackdropView }
5669
+ ...transmissionBackdropView === void 0 ? { backdropView: pipelineState.defaultWhiteTextureView } : { backdropView: transmissionBackdropView }
5473
5670
  } : null,
5474
- physicalTextureInjections
5671
+ physicalTextureInjections,
5672
+ surfaceMediumResources
5475
5673
  );
5476
5674
  if (runtime.device.caps.storageBuffer) {
5477
5675
  smMergedEntries.push({
@@ -5500,6 +5698,14 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5500
5698
  entityKey,
5501
5699
  materialHandle: smMaterialHandle,
5502
5700
  shader: smShaderId,
5701
+ surfaceModel: submeshMaterial.surfaceModel,
5702
+ layoutIdentity: getOpaqueResourceIdentity(smMaterialBgl),
5703
+ bindings: smMergedEntries.map((entry) => entry.binding),
5704
+ graphResources: {
5705
+ rawDepth: surfaceRawDepthView != null,
5706
+ nearestLayer: surfaceNearestLayerView != null,
5707
+ nearestDepth: surfaceNearestDepthView != null
5708
+ },
5503
5709
  paramSnapshot: submeshMaterial.paramSnapshot,
5504
5710
  handleTypes: materialCacheHandles.map((handle) => typeof handle)
5505
5711
  })}`
@@ -5538,7 +5744,7 @@ function buildPerSubmeshMaterialBg(deps, submeshMaterial, entityKey, materialWor
5538
5744
  "miss"
5539
5745
  );
5540
5746
  }
5541
- if (smMaterialHandle !== void 0 && !smHasVideoFields && materialResourcesResident && !hasActiveTransmissionBackdrop) {
5747
+ if (smMaterialHandle !== void 0 && !smHasVideoFields && (submeshMaterial.textureSources?.size ?? 0) === 0 && materialResourcesResident && !hasActiveTransmissionBackdrop) {
5542
5748
  if (materialCacheKey !== void 0) {
5543
5749
  materialBgAssemblyCache.set(materialCacheKey, {
5544
5750
  material: submeshMaterial,
@@ -5592,7 +5798,6 @@ function resolveMaterialSkylight(runtime, pipelineState, skylight, skylightCount
5592
5798
  prefilterView: activeViews.pref,
5593
5799
  prefilterSampler: skylightFallback.sampler,
5594
5800
  brdfLutView: activeViews.brdf,
5595
- brdfLutSampler: skylightFallback.sampler,
5596
5801
  intensityBuffer: skylightFallback.intensityBuffer
5597
5802
  } : {
5598
5803
  irradianceView: skylightFallback.irradianceView,
@@ -5600,7 +5805,6 @@ function resolveMaterialSkylight(runtime, pipelineState, skylight, skylightCount
5600
5805
  prefilterView: skylightFallback.prefilterView,
5601
5806
  prefilterSampler: skylightFallback.sampler,
5602
5807
  brdfLutView: skylightFallback.brdfLutView,
5603
- brdfLutSampler: skylightFallback.sampler,
5604
5808
  intensityBuffer: skylightFallback.intensityBuffer
5605
5809
  };
5606
5810
  return { skylightResources, activeViews };
@@ -5615,6 +5819,111 @@ function prepareMaterialSkylight(c) {
5615
5819
  );
5616
5820
  }
5617
5821
 
5822
+ // src/record/probe-blend-buffer.ts
5823
+ function isProbeBlendProjection(input) {
5824
+ return !Array.isArray(input);
5825
+ }
5826
+ function retireProbeBlendRecordBuffer(buffer) {
5827
+ const destroy = () => {
5828
+ if (!buffer.isDestroyed) void buffer.destroy();
5829
+ };
5830
+ void buffer.device.queue.onSubmittedWorkDone().then(destroy, destroy);
5831
+ }
5832
+ function createCompleteProbeBlendBuffer(device, requiredCapacity, records) {
5833
+ const created = device.createBuffer({
5834
+ label: "probe-blend-records",
5835
+ size: requiredCapacity * PROBE_BLEND_RECORD_STRIDE,
5836
+ usage: (device.caps.storageBuffer ? GPU_BUFFER_USAGE_STORAGE : GPU_BUFFER_USAGE_UNIFORM) | GPU_BUFFER_USAGE_COPY_DST,
5837
+ mappedAtCreation: false
5838
+ });
5839
+ if (!created.ok) throw created.error;
5840
+ const candidate = new GpuBuffer(device, created.value);
5841
+ const cache3 = /* @__PURE__ */ new Map();
5842
+ try {
5843
+ for (const { cacheKey, record } of records) {
5844
+ const uploaded = device.queue.writeBuffer(
5845
+ candidate.handle,
5846
+ probeBlendRecordOffset(record.objectKey),
5847
+ record.bytes
5848
+ );
5849
+ if (!uploaded.ok) throw uploaded.error;
5850
+ cache3.set(cacheKey, {
5851
+ generation: record.generation,
5852
+ bytes: new Uint8Array(record.bytes)
5853
+ });
5854
+ }
5855
+ } catch (cause) {
5856
+ void candidate.destroy();
5857
+ throw cause;
5858
+ }
5859
+ return { buffer: candidate, cache: cache3 };
5860
+ }
5861
+ function ensureProbeBlendRecordBuffer(device, frameState, input) {
5862
+ const projection = input !== void 0 && isProbeBlendProjection(input) ? input : void 0;
5863
+ const records = input === void 0 ? [] : projection?.records ?? input;
5864
+ let buffer = frameState.probeBlendRecordBuffer;
5865
+ const accepted = frameState.probeBlendRecordProjection;
5866
+ if (projection !== void 0 && accepted?.projection === projection && accepted.device === device) {
5867
+ if (records.length === 0) return void 0;
5868
+ if (accepted.buffer === buffer && buffer !== void 0 && !buffer.isDestroyed) {
5869
+ return buffer.handle;
5870
+ }
5871
+ }
5872
+ if (records.length === 0) {
5873
+ if (projection !== void 0) {
5874
+ frameState.probeBlendBuffers.clear();
5875
+ frameState.probeBlendRecordProjection = {
5876
+ projection,
5877
+ device,
5878
+ buffer: void 0
5879
+ };
5880
+ }
5881
+ return void 0;
5882
+ }
5883
+ const requiredCapacity = projection?.capacity ?? records.reduce((capacity, { record }) => Math.max(capacity, record.objectKey + 2), 1);
5884
+ const grows = buffer === void 0 || buffer.isDestroyed || buffer.device !== device || frameState.probeBlendRecordBufferCapacity < requiredCapacity;
5885
+ 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;
5886
+ const requiresCompletePublish = grows || projection !== void 0 && (!hasAcceptedBaseline || projection.dirtyRecords.length > 1);
5887
+ if (requiresCompletePublish) {
5888
+ const candidate = createCompleteProbeBlendBuffer(device, requiredCapacity, records);
5889
+ const previous = buffer;
5890
+ buffer = candidate.buffer;
5891
+ frameState.probeBlendRecordBuffer = candidate.buffer;
5892
+ frameState.probeBlendRecordBufferCapacity = requiredCapacity;
5893
+ frameState.probeBlendBuffers.clear();
5894
+ for (const [key, value] of candidate.cache) frameState.probeBlendBuffers.set(key, value);
5895
+ if (projection === void 0) delete frameState.probeBlendRecordProjection;
5896
+ else frameState.probeBlendRecordProjection = { projection, device, buffer: candidate.buffer };
5897
+ if (previous !== void 0) retireProbeBlendRecordBuffer(previous);
5898
+ return candidate.buffer.handle;
5899
+ }
5900
+ if (buffer === void 0) return void 0;
5901
+ const changed = projection?.dirtyRecords ?? records;
5902
+ const cacheUpdates = [];
5903
+ for (const { cacheKey, record } of changed) {
5904
+ const cached = frameState.probeBlendBuffers.get(cacheKey);
5905
+ const unchanged = cached !== void 0 && cached.generation === record.generation && cached.bytes.length === record.bytes.length && cached.bytes.every((value, index) => value === record.bytes[index]);
5906
+ if (unchanged) continue;
5907
+ const uploaded = device.queue.writeBuffer(
5908
+ buffer.handle,
5909
+ probeBlendRecordOffset(record.objectKey),
5910
+ record.bytes
5911
+ );
5912
+ if (!uploaded.ok) throw uploaded.error;
5913
+ cacheUpdates.push([
5914
+ cacheKey,
5915
+ { generation: record.generation, bytes: new Uint8Array(record.bytes) }
5916
+ ]);
5917
+ }
5918
+ for (const [cacheKey, value] of cacheUpdates) frameState.probeBlendBuffers.set(cacheKey, value);
5919
+ for (const cacheKey of projection?.removedCacheKeys ?? []) {
5920
+ frameState.probeBlendBuffers.delete(cacheKey);
5921
+ }
5922
+ if (projection === void 0) delete frameState.probeBlendRecordProjection;
5923
+ else frameState.probeBlendRecordProjection = { projection, device, buffer };
5924
+ return buffer.handle;
5925
+ }
5926
+
5618
5927
  // src/record/main-pass-geometry.ts
5619
5928
  function sameOpaqueTemporalDraw(a, b) {
5620
5929
  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 +5975,10 @@ function isGpuDrivenMainClaimedSubmesh(c, source, submeshIndex, drawIndices) {
5666
5975
  if (drawItemIndex === void 0 || draw === void 0) return false;
5667
5976
  const material = source.materials[draw.materialSlot] ?? source.material;
5668
5977
  const sourceDrawItemIndex = gpuDrivenSourceDrawItemIndex(draw, drawItemIndex);
5978
+ const stableWorld = c.gpuDrivenWorldKeys?.[source.worldId] ?? source.worldId;
5669
5979
  return c.gpuDrivenDrawKeys?.has(
5670
5980
  gpuDrivenDrawKey(
5671
- worldEntityKey(source.worldId, source.entityKey),
5981
+ worldEntityKey(stableWorld, source.entityKey),
5672
5982
  material.materialHandle ?? -1,
5673
5983
  sourceDrawItemIndex
5674
5984
  )
@@ -5754,6 +6064,9 @@ function geometryRenderStateForPass(base, passKind, coverageOnly = false) {
5754
6064
  depthCompare: "less-equal"
5755
6065
  };
5756
6066
  }
6067
+ function authoredTransparentDepthWrite(transparent, renderState) {
6068
+ return (transparent === true || renderState?.blend !== void 0) && renderState?.depthWriteEnabled === true;
6069
+ }
5757
6070
  function geometryRecordPhase(passKind, segment) {
5758
6071
  const pass = passKind === "deferred" ? "g-buffer" : "forward";
5759
6072
  return `record/graph-execute/${pass}/${segment}`;
@@ -5768,13 +6081,16 @@ function submitSubmeshDraws(pass, state, pipeline, instanceDraws, indexed, index
5768
6081
  state.pipeline = pipeline;
5769
6082
  }
5770
6083
  for (const instanceDraw of instanceDraws) {
5771
- if (instanceDraw.instanceBuffer !== state.instancesBuffer || instanceDraw.probeOffset !== state.probeOffset) {
5772
- if (instanceDraw.probeOffset < 0) {
6084
+ if (instanceDraw.instanceBuffer !== state.instancesBuffer || instanceDraw.instanceBindGroup !== state.instanceBindGroup || instanceDraw.probeOffset !== state.probeOffset) {
6085
+ if (instanceDraw.dynamicOffsets !== void 0) {
6086
+ pass.setBindGroup(3, instanceDraw.instanceBindGroup, instanceDraw.dynamicOffsets);
6087
+ } else if (instanceDraw.probeOffset < 0) {
5773
6088
  pass.setBindGroup(3, instanceDraw.instanceBindGroup);
5774
6089
  } else {
5775
6090
  pass.setBindGroup(3, instanceDraw.instanceBindGroup, [instanceDraw.probeOffset]);
5776
6091
  }
5777
6092
  state.instancesBuffer = instanceDraw.instanceBuffer;
6093
+ state.instanceBindGroup = instanceDraw.instanceBindGroup;
5778
6094
  state.probeOffset = instanceDraw.probeOffset;
5779
6095
  }
5780
6096
  if (indexed) {
@@ -5782,7 +6098,7 @@ function submitSubmeshDraws(pass, state, pipeline, instanceDraws, indexed, index
5782
6098
  } else {
5783
6099
  pass.draw(vertexCount, instanceDraw.instanceCount, 0, 0);
5784
6100
  }
5785
- onDraw?.();
6101
+ onDraw?.(instanceDraw, indexed ? "draw-indexed" : "draw");
5786
6102
  }
5787
6103
  }
5788
6104
  function recordPointsLinesDraw(pass, plan) {
@@ -5793,7 +6109,7 @@ function recordPointsLinesDraw(pass, plan) {
5793
6109
  }
5794
6110
  pass.draw(plan.vertexCount, 1, 0, 0);
5795
6111
  }
5796
- function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sampleCount, meshGroup2, meshBindGroup, resolveMaterialBindGroup, passKind = "forward", selectedDispatch, colorFormats = [], coverageOnly = false) {
6112
+ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sampleCount, meshGroup2, meshBindGroup, resolveMaterialBindGroup, passKind = "forward", selectedDispatch, colorFormats = [], coverageOnly = false, fragmentEntryPoint, surfacePass, transparentDepthWrite = false) {
5797
6113
  const {
5798
6114
  runtime,
5799
6115
  pipelineState,
@@ -5829,6 +6145,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5829
6145
  const bindingState = {
5830
6146
  pipeline: null,
5831
6147
  instancesBuffer: null,
6148
+ instanceBindGroup: null,
5832
6149
  probeOffset: -1
5833
6150
  };
5834
6151
  const identityInstanceBuffer = pipelineState.identityInstanceBuffer;
@@ -5848,7 +6165,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5848
6165
  const recordOcclusionCandidate = (draw) => {
5849
6166
  draw();
5850
6167
  };
5851
- const resolveMaterialPipeline = (materialShaderId, renderState, topology, indexFormat, variantSet, colorFormat, layoutProjection, vertexEntry, fragmentEntry, textureMask) => {
6168
+ const resolveMaterialPipeline = (materialShaderId, renderState, topology, indexFormat, variantSet, colorFormat, layoutProjection, vertexEntry, fragmentEntry, textureMask, layoutKind) => {
5852
6169
  const pipelineVariantSet = withCoverageVariant(variantSet);
5853
6170
  const reflectionFallbackFormats = materialShaderId === "forgeax::default-standard-pbr" && c.reflectionFallbackColorFormat !== void 0 ? passKind === "deferred" ? colorFormats.slice(1) : [c.reflectionFallbackColorFormat] : void 0;
5854
6171
  const renderStateKey = renderStateHash(renderState);
@@ -5856,12 +6173,12 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5856
6173
  const cachedLookups = shaderLookupCache?.get(renderStateKey);
5857
6174
  if (cachedLookups !== void 0) {
5858
6175
  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(",")) {
6176
+ 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
6177
  return cached.handle;
5861
6178
  }
5862
6179
  }
5863
6180
  }
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);
6181
+ 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
6182
  if (!resolvedVariantSetResult.ok) {
5866
6183
  runtime.errorRegistry.fire(resolvedVariantSetResult.error);
5867
6184
  return null;
@@ -5884,7 +6201,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5884
6201
  void 0,
5885
6202
  layoutProjection,
5886
6203
  void 0,
5887
- void 0,
6204
+ layoutKind,
5888
6205
  void 0,
5889
6206
  reflectionFallbackFormats,
5890
6207
  vertexEntry,
@@ -5909,6 +6226,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5909
6226
  colorFormatOverride: colorFormat,
5910
6227
  additionalColorFormats: reflectionFallbackFormats,
5911
6228
  textureMask,
6229
+ layoutKind,
5912
6230
  handle
5913
6231
  };
5914
6232
  if (shaderLookupCache === void 0) {
@@ -5927,6 +6245,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
5927
6245
  for (let i = 0; i < validatedOrdered.length; i++) {
5928
6246
  const entry = validatedOrdered[i];
5929
6247
  if (entry === void 0) continue;
6248
+ if (c.foldDispatchPlan?.skipIndices.has(i) === true) continue;
5930
6249
  const pointsLinesSubmission = c.pointsLines?.prepare(entry, clusteredLighting);
5931
6250
  if (entry.source.pointsLines !== void 0 && pointsLinesSubmission?.plan.drawCount !== 1)
5932
6251
  continue;
@@ -6009,8 +6328,17 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6009
6328
  }
6010
6329
  }
6011
6330
  dispatchCounts.unlit += 1;
6012
- const instanceDraws = resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, false);
6013
- if (instanceDraws === null) continue;
6331
+ const fold = c.foldDispatchPlan?.headBuckets.get(i);
6332
+ const foldBuffer = fold === void 0 ? null : resolveFoldInstanceBuffer(c, fold, i);
6333
+ const baseInstanceDraws = fold === void 0 ? resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, false) : foldBuffer === null ? null : [
6334
+ {
6335
+ instanceBuffer: foldBuffer,
6336
+ instanceBindGroup: resolveGeometryInstancesBindGroup(c, foldBuffer, void 0),
6337
+ probeOffset: -1,
6338
+ instanceCount: fold.bucketSize
6339
+ }
6340
+ ];
6341
+ if (baseInstanceDraws === null) continue;
6014
6342
  let group2BindGroup = meshGroup2;
6015
6343
  meshGroup2DynamicOffsets[0] = i * MESH_PER_ENTITY_STRIDE;
6016
6344
  let group2DynamicOffsets = meshGroup2DynamicOffsets;
@@ -6153,10 +6481,11 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6153
6481
  if (passKind === "forward" && isGpuDrivenMainClaimedSubmesh(c, entry.source, smIdx, gpuDrivenDrawIndices)) {
6154
6482
  continue;
6155
6483
  }
6156
- const draws = selectedDispatch === void 0 ? [void 0] : materialPasses.get(entry.renderableIndex)?.get(submeshMaterial.materialHandle ?? 0) ?? [];
6484
+ const selectedMaterialPasses = materialPasses.get(entry.renderableIndex)?.get(submeshMaterial.materialHandle ?? 0);
6485
+ 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
6486
  for (const selectedPass of draws) {
6158
6487
  const vertexEntry = passKind === "temporal" ? void 0 : selectedPass?.vertexEntry;
6159
- const fragmentEntry = passKind === "temporal" ? void 0 : selectedPass?.fragmentEntry;
6488
+ const fragmentEntry = passKind === "temporal" ? void 0 : fragmentEntryPoint ?? selectedPass?.fragmentEntry;
6160
6489
  const selectedShaderId = selectedPass === void 0 ? submeshMaterial.materialShaderId : selectedPass.materialShaderId;
6161
6490
  const selectedRenderState = selectedPass === void 0 ? submeshMaterial.renderState : selectedPass.renderState;
6162
6491
  const selectedStencil = (selectedPass === void 0 ? entry.stencilReference : selectedPass.stencilReference) ?? 0;
@@ -6202,7 +6531,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6202
6531
  pass.setBindGroup(1, perSubmeshBg, materialGroup1DynamicOffsets, 0, 1);
6203
6532
  const smTopology = sm.topology;
6204
6533
  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);
6534
+ const probeBlendAvailable = probeBlendRecordAvailable && (isStandardPbrMaterialShader(smMaterialShaderId) || submeshMaterial.surfaceModel === "single-layer-medium");
6206
6535
  const isSpriteShader = smMaterialShaderId === "forgeax::sprite" || smMaterialShaderId === "forgeax::sprite-lit";
6207
6536
  const basePipelineRenderState = isSpriteShader ? {
6208
6537
  ...selectedRenderState,
@@ -6211,11 +6540,21 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6211
6540
  cullMode: "none",
6212
6541
  blend: selectedRenderState?.blend ?? SPRITE_PREMULTIPLIED_ALPHA_BLEND
6213
6542
  } : geometryRenderStateForTopology(smTopology, selectedRenderState);
6214
- const pipelineRenderState = geometryRenderStateForPass(
6543
+ let pipelineRenderState = geometryRenderStateForPass(
6215
6544
  basePipelineRenderState,
6216
6545
  passKind,
6217
6546
  coverageOnly
6218
6547
  );
6548
+ if (transparentDepthWrite && passKind === "forward" && (submeshMaterial.transparent === true || selectedRenderState?.blend !== void 0)) {
6549
+ pipelineRenderState = {
6550
+ ...pipelineRenderState,
6551
+ depthWriteEnabled: authoredTransparentDepthWrite(
6552
+ submeshMaterial.transparent,
6553
+ selectedRenderState
6554
+ ),
6555
+ depthCompare: "less-equal"
6556
+ };
6557
+ }
6219
6558
  let smPipelineHandle;
6220
6559
  let materialGroup2Contract;
6221
6560
  let materialPipelineEntry = null;
@@ -6260,7 +6599,7 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6260
6599
  );
6261
6600
  const transmissionAvailable = requestsStandardTransmissionVariant(submeshMaterial);
6262
6601
  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}`;
6602
+ const variantSet = isSpriteShader ? smMaterialShaderId === "forgeax::sprite-lit" ? materialCapabilityVariantSet : entry.source.spriteInstances !== void 0 ? "" : void 0 : entry.variantSet === void 0 ? materialCapabilityVariantSet : `${materialCapabilityVariantSet}+${entry.variantSet}`;
6264
6603
  const cachedPipeline = resolveMaterialPipeline(
6265
6604
  smMaterialShaderId,
6266
6605
  pipelineRenderState,
@@ -6271,7 +6610,8 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6271
6610
  entry.mesh.layoutProjection,
6272
6611
  vertexEntry,
6273
6612
  fragmentEntry,
6274
- submeshMaterial.standardTextureMask
6613
+ submeshMaterial.standardTextureMask,
6614
+ submeshMaterial.surfaceModel === "single-layer-medium" && passKind === "forward" ? capabilityVariantSet.includes("CLUSTER_FORWARD_AVAILABLE=true") ? "surface-direct-cluster-pbr" : "surface-direct-pbr" : void 0
6275
6615
  );
6276
6616
  materialPipelineEntry = cachedPipeline;
6277
6617
  smPipelineHandle = cachedPipeline?.pipeline ?? null;
@@ -6291,13 +6631,18 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6291
6631
  }
6292
6632
  continue;
6293
6633
  }
6294
- const instanceDraws2 = resolveGeometryInstanceBuffer(
6634
+ const resolvedInstanceDraws = probeBlendAvailable ? resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, true) : baseInstanceDraws;
6635
+ if (resolvedInstanceDraws === null) continue;
6636
+ const compactDrawIndex = gpuDrivenDrawIndices.get(smIdx);
6637
+ const compactDraw = compactDrawIndex === void 0 ? void 0 : entry.source.gpuDrivenDraws?.[compactDrawIndex];
6638
+ const sourceDrawItemIndex = compactDrawIndex === void 0 || compactDraw === void 0 ? smIdx : gpuDrivenSourceDrawItemIndex(compactDraw, compactDrawIndex);
6639
+ const instanceDraws = submeshMaterial.surfaceModel === "single-layer-medium" && passKind === "forward" ? resolveSurfaceDirectInstanceDraws(
6295
6640
  c,
6296
6641
  entry,
6297
- identityInstanceDraws,
6298
- probeBlendAvailable
6299
- );
6300
- if (instanceDraws2 === null) continue;
6642
+ sourceDrawItemIndex,
6643
+ resolvedInstanceDraws
6644
+ ) : resolvedInstanceDraws;
6645
+ if (instanceDraws === null) continue;
6301
6646
  if (!isSkinEntry) {
6302
6647
  materialGroup2Contract = materialPipelineEntry?.group2Contract;
6303
6648
  if (materialGroup2Contract === void 0) continue;
@@ -6339,12 +6684,29 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6339
6684
  pass,
6340
6685
  bindingState,
6341
6686
  smPipelineHandle,
6342
- instanceDraws2,
6687
+ instanceDraws,
6343
6688
  entry.mesh.indexed,
6344
6689
  sm.indexCount,
6345
6690
  sm.vertexCount,
6346
6691
  sm.indexOffset,
6347
- () => c.onRenderableDraw?.(entry)
6692
+ (draw, command) => {
6693
+ c.onRenderableDraw?.(entry, smIdx);
6694
+ if (surfacePass === void 0 || draw.surfaceFrameBase === void 0) return;
6695
+ c.frameState.surfaceSubmissionObservation?.record(surfacePass, {
6696
+ kind: command,
6697
+ count: entry.mesh.indexed ? sm.indexCount : sm.vertexCount,
6698
+ first: entry.mesh.indexed ? sm.indexOffset : 0,
6699
+ instanceCount: draw.instanceCount,
6700
+ firstInstance: 0,
6701
+ surfaceFrameBase: draw.surfaceFrameBase,
6702
+ memberIds: draw.surfaceMemberIds ?? [],
6703
+ pipelineIdentity: getOpaqueResourceIdentity(smPipelineHandle),
6704
+ ...materialPipelineEntry?.receipt === void 0 ? {} : {
6705
+ receiptIdentity: materialPipelineEntry.receipt.identity,
6706
+ receiptGeneration: materialPipelineEntry.receipt.generation
6707
+ }
6708
+ });
6709
+ }
6348
6710
  )
6349
6711
  );
6350
6712
  } else {
@@ -6357,12 +6719,29 @@ function recordGeometryDraws(c, pass, matchedMaterials, materialSlotIndices, sam
6357
6719
  pass,
6358
6720
  bindingState,
6359
6721
  smPipelineHandle,
6360
- instanceDraws2,
6722
+ instanceDraws,
6361
6723
  entry.mesh.indexed,
6362
6724
  sm.indexCount,
6363
6725
  sm.vertexCount,
6364
6726
  sm.indexOffset,
6365
- () => c.onRenderableDraw?.(entry)
6727
+ (draw, command) => {
6728
+ c.onRenderableDraw?.(entry, smIdx);
6729
+ if (surfacePass === void 0 || draw.surfaceFrameBase === void 0) return;
6730
+ c.frameState.surfaceSubmissionObservation?.record(surfacePass, {
6731
+ kind: command,
6732
+ count: entry.mesh.indexed ? sm.indexCount : sm.vertexCount,
6733
+ first: entry.mesh.indexed ? sm.indexOffset : 0,
6734
+ instanceCount: draw.instanceCount,
6735
+ firstInstance: 0,
6736
+ surfaceFrameBase: draw.surfaceFrameBase,
6737
+ memberIds: draw.surfaceMemberIds ?? [],
6738
+ pipelineIdentity: getOpaqueResourceIdentity(smPipelineHandle),
6739
+ ...materialPipelineEntry?.receipt === void 0 ? {} : {
6740
+ receiptIdentity: materialPipelineEntry.receipt.identity,
6741
+ receiptGeneration: materialPipelineEntry.receipt.generation
6742
+ }
6743
+ });
6744
+ }
6366
6745
  )
6367
6746
  )
6368
6747
  );
@@ -6574,8 +6953,10 @@ function resolveStorageInstanceChunks(c, entry, inst, cap, probeBuffer, probeOff
6574
6953
  activeBuffer.buffer.handle,
6575
6954
  probeBuffer
6576
6955
  ),
6956
+ ...probeBuffer === void 0 ? {} : { probeBuffer },
6577
6957
  probeOffset,
6578
- instanceCount: count
6958
+ instanceCount: count,
6959
+ firstInstanceOrdinal: start
6579
6960
  });
6580
6961
  }
6581
6962
  if (chunks !== void 0) {
@@ -6601,6 +6982,22 @@ function resolveStorageInstanceChunks(c, entry, inst, cap, probeBuffer, probeOff
6601
6982
  function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbeBlend) {
6602
6983
  const { runtime, pipelineState, frameState } = c;
6603
6984
  const inst = entry.source.instances;
6985
+ if (entry.source.spriteInstances !== void 0) {
6986
+ const { buffer, count } = resolveSpriteInstancesBuffer(
6987
+ c,
6988
+ entry,
6989
+ pipelineState.identityInstanceBuffer,
6990
+ 0
6991
+ );
6992
+ return count === 0 ? [] : [
6993
+ {
6994
+ instanceBuffer: buffer,
6995
+ instanceBindGroup: resolveGeometryInstancesBindGroup(c, buffer, void 0),
6996
+ probeOffset: -1,
6997
+ instanceCount: count
6998
+ }
6999
+ ];
7000
+ }
6604
7001
  const probeBinding = !useProbeBlend || !runtime.device.caps.storageBuffer || entry.source.probeBlendRecord === void 0 ? void 0 : resolveProbeBlendBuffer(
6605
7002
  c,
6606
7003
  entry.source.probeBlendRecord,
@@ -6617,6 +7014,7 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6617
7014
  pipelineState.identityInstanceBuffer,
6618
7015
  probeBinding?.buffer
6619
7016
  ),
7017
+ ...probeBinding?.buffer === void 0 ? {} : { probeBuffer: probeBinding.buffer },
6620
7018
  probeOffset: probeBinding?.offset ?? -1
6621
7019
  }
6622
7020
  ];
@@ -6729,8 +7127,10 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6729
7127
  active.buffer.handle,
6730
7128
  probeBinding?.buffer
6731
7129
  ),
7130
+ ...probeBinding?.buffer === void 0 ? {} : { probeBuffer: probeBinding.buffer },
6732
7131
  probeOffset: probeBinding?.offset ?? -1,
6733
- instanceCount: count
7132
+ instanceCount: count,
7133
+ firstInstanceOrdinal: start
6734
7134
  });
6735
7135
  }
6736
7136
  if (chunks !== void 0) {
@@ -6784,6 +7184,7 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6784
7184
  if (!bufRes.ok) {
6785
7185
  runtime.errorRegistry.fire(bufRes.error);
6786
7186
  reportInstanceFailure(c, inst, bufRes.error, requestedBytes, cap);
7187
+ return null;
6787
7188
  } else {
6788
7189
  if (cached !== void 0 && !cached.buffer.isDestroyed) {
6789
7190
  const r = cached.buffer.destroy();
@@ -6860,43 +7261,61 @@ function resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, useProbe
6860
7261
  {
6861
7262
  instanceBuffer,
6862
7263
  instanceBindGroup: resolveGeometryInstancesBindGroup(c, instanceBuffer, probeBinding?.buffer),
7264
+ ...probeBinding?.buffer === void 0 ? {} : { probeBuffer: probeBinding.buffer },
6863
7265
  probeOffset: probeBinding?.offset ?? -1,
6864
7266
  instanceCount
6865
7267
  }
6866
7268
  ];
6867
7269
  }
7270
+ function resolveSurfaceDirectInstanceDraws(c, entry, drawItemIndex, draws) {
7271
+ const resolve = c.gpuDrivenStandardPbrFrameResources?.surfaceDirectInstances;
7272
+ if (resolve === void 0) {
7273
+ c.runtime.errorRegistry.fire(
7274
+ new RhiError({
7275
+ code: "rhi-not-available",
7276
+ expected: "the prepared Surface producer publishes the direct slot-3 resource closure",
7277
+ hint: "prepare the retained Surface frame before recording direct medium draws"
7278
+ })
7279
+ );
7280
+ return null;
7281
+ }
7282
+ const resolved = [];
7283
+ for (const draw of draws) {
7284
+ const direct = resolve({
7285
+ worldId: entry.source.worldId,
7286
+ entityKey: entry.source.entityKey,
7287
+ drawItemIndex,
7288
+ instanceCount: draw.instanceCount,
7289
+ firstInstanceOrdinal: draw.firstInstanceOrdinal ?? 0,
7290
+ instanceBuffer: draw.instanceBuffer,
7291
+ ...draw.probeBuffer === void 0 ? {} : { probeBuffer: draw.probeBuffer },
7292
+ ...draw.probeOffset < 0 ? {} : {
7293
+ probeOffset: draw.probeOffset
7294
+ }
7295
+ });
7296
+ if (!direct.ok) {
7297
+ c.runtime.errorRegistry.fire(direct.error);
7298
+ return null;
7299
+ }
7300
+ resolved.push({
7301
+ ...draw,
7302
+ instanceBindGroup: direct.value.bindGroup,
7303
+ dynamicOffsets: direct.value.dynamicOffsets,
7304
+ surfaceFrameBase: direct.value.frameBase,
7305
+ surfaceMemberIds: direct.value.memberIds
7306
+ });
7307
+ }
7308
+ return resolved;
7309
+ }
6868
7310
  function resolveProbeBlendBuffer(c, record, entityKey) {
6869
7311
  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
7312
  if (record === void 0) throw new Error("probe blend record is required for probe allocation");
6872
7313
  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 };
7314
+ const buffer = ensureProbeBlendRecordBuffer(runtime.device, frameState, [
7315
+ { cacheKey: entityKey, record }
7316
+ ]);
7317
+ if (buffer === void 0) throw new Error("probe blend record buffer allocation failed");
7318
+ return { buffer, offset: probeBlendRecordOffset(record.objectKey) };
6900
7319
  }
6901
7320
  function resolveGeometryInstancesBindGroup(c, instanceBuffer, probeBuffer) {
6902
7321
  const { runtime, pipelineState, frameState, bindGroupCounts } = c;
@@ -6936,30 +7355,6 @@ function resolveGeometryInstancesBindGroup(c, instanceBuffer, probeBuffer) {
6936
7355
  bindGroupCounts
6937
7356
  );
6938
7357
  }
6939
- function interleaveSpriteInstanceBuffer(transforms, regions, includePrevious = false) {
6940
- const count = transforms.length / 16;
6941
- const stride = includePrevious ? 36 : 20;
6942
- const regionOffset = includePrevious ? 32 : 16;
6943
- const out = new Float32Array(count * stride);
6944
- for (let i = 0; i < count; i++) {
6945
- const dstBase = i * stride;
6946
- const transformBase = i * 16;
6947
- const regionBase = i * 4;
6948
- for (let k = 0; k < 16; k++) out[dstBase + k] = transforms[transformBase + k] ?? 0;
6949
- if (includePrevious) {
6950
- for (let k = 0; k < 16; k++) {
6951
- out[dstBase + 16 + k] = transforms[transformBase + k] ?? 0;
6952
- }
6953
- }
6954
- for (let k = 0; k < 4; k++) {
6955
- out[dstBase + regionOffset + k] = regions[regionBase + k] ?? 0;
6956
- }
6957
- }
6958
- return out;
6959
- }
6960
- function spriteInstancesCacheHit(entry, snapshot, requestedBytes) {
6961
- return entry !== void 0 && entry.uploadedArchVersion === snapshot.archVersion && entry.uploadedByteLength === requestedBytes;
6962
- }
6963
7358
  function computeSplitLdrSprite(validatedOrdered, tonemapActive, dispatch) {
6964
7359
  if (tonemapActive) return false;
6965
7360
  if (dispatch !== void 0 && dispatch.length > 0) {
@@ -7219,50 +7614,10 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, resolveMaterialB
7219
7614
  const spriteInst = spriteEntry.source.instances;
7220
7615
  const useFold = foldHeadBucket !== void 0 && spriteInst === void 0;
7221
7616
  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
- }
7617
+ const buffer = resolveFoldInstanceBuffer(c, foldHeadBucket, i);
7618
+ if (buffer === null) continue;
7619
+ spriteInstanceBuffer = buffer;
7620
+ spriteInstanceCount = foldHeadBucket.bucketSize;
7266
7621
  } else if (spriteInst !== void 0) {
7267
7622
  const uniformFallback = runtime.device.caps.storageBuffer === false;
7268
7623
  let spriteBufUsage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
@@ -7288,7 +7643,7 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, resolveMaterialB
7288
7643
  );
7289
7644
  spritePass.setBindGroup(3, spriteInstBg);
7290
7645
  spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
7291
- c.onRenderableDraw?.(spriteEntry);
7646
+ c.onRenderableDraw?.(spriteEntry, 0);
7292
7647
  continue;
7293
7648
  }
7294
7649
  spriteBufUsage = GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
@@ -7308,158 +7663,83 @@ function recordSpriteEntityDraws(c, spritePass, matchedIndices, resolveMaterialB
7308
7663
  code: "limit-exceeded",
7309
7664
  expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
7310
7665
  hint: "reduce the sprite batch to fit within device.limits.maxStorageBufferBindingSize or use a storage-capable backend",
7311
- detail: {
7312
- maxStorageBufferBindingSize: cap,
7313
- requestedBytes
7314
- }
7315
- })
7316
- );
7317
- } else {
7318
- const cachedSprite = frameState.instanceBuffers.get(
7319
- worldEntityKey(spriteEntry.source.worldId, spriteInst.cacheKey)
7320
- );
7321
- let activeSprite = null;
7322
- if (cachedSprite !== void 0 && cachedSprite.uploadedArchVersion === spriteInst.archVersion && cachedSprite.uploadedByteLength === requestedBytes) {
7323
- activeSprite = cachedSprite;
7324
- } else if (requestedBytes > 0) {
7325
- const bufRes = runtime.device.createBuffer({
7326
- size: requestedBytes,
7327
- usage: spriteBufUsage,
7328
- mappedAtCreation: false
7329
- });
7330
- if (!bufRes.ok) {
7331
- runtime.errorRegistry.fire(bufRes.error);
7332
- } else {
7333
- if (cachedSprite !== void 0 && !cachedSprite.buffer.isDestroyed) {
7334
- const r = cachedSprite.buffer.destroy();
7335
- if (!r.ok) runtime.errorRegistry.fire(r.error);
7336
- }
7337
- const newBuf = new GpuBuffer(runtime.device, bufRes.value);
7338
- activeSprite = {
7339
- buffer: newBuf,
7340
- uploadedArchVersion: spriteInst.archVersion,
7341
- uploadedByteLength: requestedBytes
7342
- };
7343
- frameState.instanceBuffers.set(
7344
- worldEntityKey(spriteEntry.source.worldId, spriteInst.cacheKey),
7345
- activeSprite
7346
- );
7347
- }
7348
- }
7349
- if (activeSprite !== null) {
7350
- const writeRes = runtime.device.queue.writeBuffer(
7351
- activeSprite.buffer.handle,
7352
- 0,
7353
- instancePayload
7354
- );
7355
- if (!writeRes.ok) {
7356
- runtime.errorRegistry.fire(writeRes.error);
7357
- } else {
7358
- spriteInstanceBuffer = activeSprite.buffer.handle;
7359
- spriteInstanceCount = Math.max(1, spriteInst.instanceCount);
7360
- }
7361
- }
7362
- }
7363
- }
7364
- }
7365
- const _si = resolveSpriteInstancesBuffer(
7366
- c,
7367
- spriteEntry,
7368
- spriteInstanceBuffer,
7369
- spriteInstanceCount
7370
- );
7371
- spriteInstanceBuffer = _si.buffer;
7372
- spriteInstanceCount = _si.count;
7373
- const spriteGroup2 = entityShaderId === "forgeax::sprite-lit" && c.standardLighting?.kind === "clustered" ? c.hdrpClusterBindGroup : meshBindGroup;
7374
- const spriteInstancesBg = resolveGeometryInstancesBindGroup(c, spriteInstanceBuffer, void 0);
7375
- spritePass.setBindGroup(2, spriteGroup2, [i * MESH_PER_ENTITY_STRIDE]);
7376
- const materialSlot = materialSlotIndices[i]?.[0] ?? 0;
7377
- const spritePassBg = resolveMaterialBindGroup(
7378
- materialSlot,
7379
- spriteEntry.source.material,
7380
- spriteEntry.source.entityKey,
7381
- spriteEntry.world ?? world
7382
- );
7383
- spritePass.setBindGroup(1, spritePassBg, [materialSlot * MATERIAL_PER_ENTITY_STRIDE]);
7384
- spritePass.setBindGroup(3, spriteInstancesBg);
7385
- spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
7386
- c.onRenderableDraw?.(spriteEntry);
7387
- }
7388
- }
7389
- function resolveSpriteInstancesBuffer(c, spriteEntry, fallbackBuffer, fallbackCount) {
7390
- const { runtime, frameState } = c;
7391
- let buffer = fallbackBuffer;
7392
- let count = fallbackCount;
7393
- const spriteInstancesSnap = spriteEntry.source.spriteInstances;
7394
- if (spriteInstancesSnap !== void 0) {
7395
- const uniformFallback = runtime.device.caps.storageBuffer === false;
7396
- const interleaved = interleaveSpriteInstanceBuffer(
7397
- spriteInstancesSnap.transforms,
7398
- spriteInstancesSnap.regions,
7399
- !uniformFallback
7400
- );
7401
- const requestedBytes = interleaved.byteLength;
7402
- const cap = runtime.device.limits.maxStorageBufferBindingSize;
7403
- if (typeof cap === "number" && requestedBytes > cap) {
7404
- runtime.errorRegistry.fire(
7405
- new RhiError({
7406
- code: "limit-exceeded",
7407
- expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
7408
- hint: "reduce SpriteInstances instance count to fit within device.limits.maxStorageBufferBindingSize (144 bytes per instance: current mat4 64B + previous mat4 64B + region 16B)",
7409
- detail: {
7410
- maxStorageBufferBindingSize: cap,
7411
- requestedBytes
7412
- }
7413
- })
7414
- );
7415
- } else {
7416
- const cachedSpriteInst = frameState.instanceBuffers.get(
7417
- worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey)
7418
- );
7419
- let activeSpriteInst = null;
7420
- if (spriteInstancesCacheHit(cachedSpriteInst, spriteInstancesSnap, requestedBytes)) {
7421
- activeSpriteInst = cachedSpriteInst ?? null;
7422
- } else if (requestedBytes > 0) {
7423
- const bufRes = runtime.device.createBuffer({
7424
- size: requestedBytes,
7425
- usage: (uniformFallback ? GPU_BUFFER_USAGE_UNIFORM : GPU_BUFFER_USAGE_STORAGE) | GPU_BUFFER_USAGE_COPY_DST,
7426
- mappedAtCreation: false
7427
- });
7428
- if (!bufRes.ok) {
7429
- runtime.errorRegistry.fire(bufRes.error);
7430
- } else {
7431
- if (cachedSpriteInst !== void 0 && !cachedSpriteInst.buffer.isDestroyed) {
7432
- const r = cachedSpriteInst.buffer.destroy();
7433
- if (!r.ok) runtime.errorRegistry.fire(r.error);
7434
- }
7435
- const newBuf = new GpuBuffer(runtime.device, bufRes.value);
7436
- activeSpriteInst = {
7437
- buffer: newBuf,
7438
- uploadedArchVersion: spriteInstancesSnap.archVersion,
7439
- uploadedByteLength: requestedBytes
7440
- };
7441
- frameState.instanceBuffers.set(
7442
- worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
7443
- activeSpriteInst
7444
- );
7445
- }
7446
- }
7447
- if (activeSpriteInst !== null && requestedBytes > 0) {
7448
- const writeRes = runtime.device.queue.writeBuffer(
7449
- activeSpriteInst.buffer.handle,
7450
- 0,
7451
- interleaved
7452
- );
7453
- if (!writeRes.ok) {
7454
- runtime.errorRegistry.fire(writeRes.error);
7666
+ detail: {
7667
+ maxStorageBufferBindingSize: cap,
7668
+ requestedBytes
7669
+ }
7670
+ })
7671
+ );
7455
7672
  } else {
7456
- buffer = activeSpriteInst.buffer.handle;
7457
- count = spriteInstancesSnap.instanceCount;
7673
+ const cachedSprite = frameState.instanceBuffers.get(
7674
+ worldEntityKey(spriteEntry.source.worldId, spriteInst.cacheKey)
7675
+ );
7676
+ let activeSprite = null;
7677
+ if (cachedSprite !== void 0 && cachedSprite.uploadedArchVersion === spriteInst.archVersion && cachedSprite.uploadedByteLength === requestedBytes) {
7678
+ activeSprite = cachedSprite;
7679
+ } else if (requestedBytes > 0) {
7680
+ const bufRes = runtime.device.createBuffer({
7681
+ size: requestedBytes,
7682
+ usage: spriteBufUsage,
7683
+ mappedAtCreation: false
7684
+ });
7685
+ if (!bufRes.ok) {
7686
+ runtime.errorRegistry.fire(bufRes.error);
7687
+ } else {
7688
+ if (cachedSprite !== void 0 && !cachedSprite.buffer.isDestroyed) {
7689
+ const r = cachedSprite.buffer.destroy();
7690
+ if (!r.ok) runtime.errorRegistry.fire(r.error);
7691
+ }
7692
+ const newBuf = new GpuBuffer(runtime.device, bufRes.value);
7693
+ activeSprite = {
7694
+ buffer: newBuf,
7695
+ uploadedArchVersion: spriteInst.archVersion,
7696
+ uploadedByteLength: requestedBytes
7697
+ };
7698
+ frameState.instanceBuffers.set(
7699
+ worldEntityKey(spriteEntry.source.worldId, spriteInst.cacheKey),
7700
+ activeSprite
7701
+ );
7702
+ }
7703
+ }
7704
+ if (activeSprite !== null) {
7705
+ const writeRes = runtime.device.queue.writeBuffer(
7706
+ activeSprite.buffer.handle,
7707
+ 0,
7708
+ instancePayload
7709
+ );
7710
+ if (!writeRes.ok) {
7711
+ runtime.errorRegistry.fire(writeRes.error);
7712
+ } else {
7713
+ spriteInstanceBuffer = activeSprite.buffer.handle;
7714
+ spriteInstanceCount = Math.max(1, spriteInst.instanceCount);
7715
+ }
7716
+ }
7458
7717
  }
7459
7718
  }
7460
7719
  }
7720
+ const _si = resolveSpriteInstancesBuffer(
7721
+ c,
7722
+ spriteEntry,
7723
+ spriteInstanceBuffer,
7724
+ spriteInstanceCount
7725
+ );
7726
+ spriteInstanceBuffer = _si.buffer;
7727
+ spriteInstanceCount = _si.count;
7728
+ const spriteGroup2 = entityShaderId === "forgeax::sprite-lit" && c.standardLighting?.kind === "clustered" ? c.hdrpClusterBindGroup : meshBindGroup;
7729
+ const spriteInstancesBg = resolveGeometryInstancesBindGroup(c, spriteInstanceBuffer, void 0);
7730
+ spritePass.setBindGroup(2, spriteGroup2, [i * MESH_PER_ENTITY_STRIDE]);
7731
+ const materialSlot = materialSlotIndices[i]?.[0] ?? 0;
7732
+ const spritePassBg = resolveMaterialBindGroup(
7733
+ materialSlot,
7734
+ spriteEntry.source.material,
7735
+ spriteEntry.source.entityKey,
7736
+ spriteEntry.world ?? world
7737
+ );
7738
+ spritePass.setBindGroup(1, spritePassBg, [materialSlot * MATERIAL_PER_ENTITY_STRIDE]);
7739
+ spritePass.setBindGroup(3, spriteInstancesBg);
7740
+ spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
7741
+ c.onRenderableDraw?.(spriteEntry, 0);
7461
7742
  }
7462
- return { buffer, count };
7463
7743
  }
7464
7744
  function transparentPassColorFormat(c, pipelineState = c.pipelineState) {
7465
7745
  if (c.transparentColorFormat !== void 0) return c.transparentColorFormat;
@@ -7668,6 +7948,29 @@ function selectLod(input) {
7668
7948
 
7669
7949
  // src/gpu-driven/batch-topology.ts
7670
7950
  var GPU_DRIVEN_SKIN_FLAG = 2147483648;
7951
+ function inspectResourceClassSplits(plan) {
7952
+ const groups = /* @__PURE__ */ new Map();
7953
+ for (const batch of plan.batches) {
7954
+ const resourceIdentity = batch.key.resourceIdentity ?? batch.key.materialResourceClass;
7955
+ const group = groups.get(resourceIdentity) ?? { batchIds: [], candidateCount: 0 };
7956
+ group.batchIds.push(batch.batchId);
7957
+ group.candidateCount += batch.candidates.length;
7958
+ groups.set(resourceIdentity, group);
7959
+ }
7960
+ const resourceClassSplits = [...groups.entries()].sort(([left], [right]) => left.localeCompare(right)).map(
7961
+ ([resourceIdentity, group]) => Object.freeze({
7962
+ resourceIdentity,
7963
+ batchIds: Object.freeze([...group.batchIds].sort((left, right) => left - right)),
7964
+ candidateCount: group.candidateCount
7965
+ })
7966
+ );
7967
+ const resourceClassSplitReasons = resourceClassSplits.length <= 1 ? [] : resourceClassSplits.map(({ resourceIdentity }) => `resource-class:${resourceIdentity}`);
7968
+ return Object.freeze({
7969
+ resourceClassCount: resourceClassSplits.length,
7970
+ resourceClassSplits: Object.freeze(resourceClassSplits),
7971
+ resourceClassSplitReasons: Object.freeze(resourceClassSplitReasons)
7972
+ });
7973
+ }
7671
7974
  var submissionCandidateMembershipCache = /* @__PURE__ */ new WeakMap();
7672
7975
  function buildSubmissionCandidateMembership(source) {
7673
7976
  const cached = submissionCandidateMembershipCache.get(source);
@@ -7766,7 +8069,8 @@ function eligibleDraws(slot) {
7766
8069
  materialResourceClass: draw.materialResourceClass,
7767
8070
  preparedIdentity,
7768
8071
  resourceIdentity: draw.materialResourceClass,
7769
- admission
8072
+ admission,
8073
+ materialPass: material.deferredPass === true ? "deferred" : "forward-only"
7770
8074
  },
7771
8075
  prepared,
7772
8076
  ...candidatePayload(draw, snapshot)
@@ -8034,6 +8338,7 @@ var BatchTopology = class {
8034
8338
  inspect() {
8035
8339
  let candidateCount = 0;
8036
8340
  for (const batch of this.batches.values()) candidateCount += batch.candidates.size;
8341
+ const resourceClasses = inspectResourceClassSplits(this.plan());
8037
8342
  return {
8038
8343
  revision: this.revision,
8039
8344
  batchCount: this.batches.size,
@@ -8045,7 +8350,10 @@ var BatchTopology = class {
8045
8350
  membershipChecks: this.membershipChecks,
8046
8351
  membershipAllocations: this.membershipAllocations,
8047
8352
  candidateAdds: this.candidateAdds,
8048
- candidateRemoves: this.candidateRemoves
8353
+ candidateRemoves: this.candidateRemoves,
8354
+ resourceClassCount: resourceClasses.resourceClassCount,
8355
+ resourceClassSplits: resourceClasses.resourceClassSplits,
8356
+ resourceClassSplitReasons: resourceClasses.resourceClassSplitReasons
8049
8357
  };
8050
8358
  }
8051
8359
  add(slot) {
@@ -8131,6 +8439,410 @@ var BatchTopology = class {
8131
8439
  };
8132
8440
  }
8133
8441
  };
8442
+ function decodeSurfaceIndirectParameters(input) {
8443
+ const ranges = input.recording.passes.flatMap(
8444
+ (pass) => pass.ranges.map((range) => ({ pass: pass.pass, ...range }))
8445
+ );
8446
+ if (input.byteOffset < 0 || input.byteLength < 0 || input.byteOffset + input.byteLength > input.bytes.byteLength) {
8447
+ return err$1({
8448
+ code: "indirect-readback-truncated",
8449
+ expected: "the indirect readback range is contained by the mapped buffer",
8450
+ hint: "retain the complete GPU indirect command copy before mapping it",
8451
+ actual: {
8452
+ byteOffset: input.byteOffset,
8453
+ byteLength: input.byteLength,
8454
+ bufferBytes: input.bytes.byteLength
8455
+ }
8456
+ });
8457
+ }
8458
+ const values = new DataView(input.bytes, input.byteOffset, input.byteLength);
8459
+ const decoded = [];
8460
+ for (const range of ranges) {
8461
+ if (range.indirectBufferIdentity !== input.indirectBufferIdentity) {
8462
+ return err$1({
8463
+ code: "indirect-readback-metadata-mismatch",
8464
+ expected: "every Surface indirect range names the copied indirect buffer",
8465
+ hint: "discard the readback and wait for the matching resource generation",
8466
+ actual: {
8467
+ pass: range.pass,
8468
+ expectedBufferIdentity: input.indirectBufferIdentity,
8469
+ actualBufferIdentity: range.indirectBufferIdentity
8470
+ }
8471
+ });
8472
+ }
8473
+ const offset = range.indirectOffset;
8474
+ if (!Number.isInteger(offset) || offset < 0 || offset % 4 !== 0 || offset + 20 > values.byteLength) {
8475
+ return err$1({
8476
+ code: "indirect-readback-truncated",
8477
+ expected: "each indirect range is a 20-byte aligned command inside the copied buffer",
8478
+ hint: "discard truncated selector readback instead of publishing partial draw parameters",
8479
+ actual: { pass: range.pass, indirectOffset: offset, readbackBytes: values.byteLength }
8480
+ });
8481
+ }
8482
+ const indexed = range.kind === "draw-indexed-indirect";
8483
+ decoded.push(
8484
+ Object.freeze({
8485
+ sequence: input.recording.sequence,
8486
+ frameId: input.recording.frameId,
8487
+ deviceGeneration: input.recording.deviceGeneration,
8488
+ resourceGeneration: input.recording.resourceGeneration,
8489
+ viewIdentity: input.recording.viewIdentity,
8490
+ pass: range.pass,
8491
+ kind: range.kind,
8492
+ indirectBufferIdentity: range.indirectBufferIdentity,
8493
+ indirectOffset: offset,
8494
+ count: values.getUint32(offset, true),
8495
+ first: values.getUint32(offset + 8, true),
8496
+ instanceCount: values.getUint32(offset + 4, true),
8497
+ baseVertex: indexed ? values.getInt32(offset + 12, true) : 0,
8498
+ firstInstance: values.getUint32(indexed ? offset + 16 : offset + 12, true)
8499
+ })
8500
+ );
8501
+ }
8502
+ return ok(Object.freeze(decoded));
8503
+ }
8504
+ var MAX_COMMANDS_PER_PASS = 32;
8505
+ function isIndirect(command) {
8506
+ return command.kind === "draw-indirect" || command.kind === "draw-indexed-indirect";
8507
+ }
8508
+ function sameReadbackPass(receipt, snapshot) {
8509
+ if (receipt.pass !== snapshot.pass || receipt.totalCommandCount !== snapshot.totalCommandCount || receipt.savedCommandCount !== snapshot.savedCommandCount || receipt.droppedCommandCount !== snapshot.droppedCommandCount || receipt.truncated !== snapshot.truncated) {
8510
+ return false;
8511
+ }
8512
+ const ranges = receipt.commands.flatMap(
8513
+ (command) => command.kind === "draw-indirect" || command.kind === "draw-indexed-indirect" ? [
8514
+ {
8515
+ kind: command.kind,
8516
+ indirectBufferIdentity: command.indirectBufferIdentity,
8517
+ indirectOffset: command.indirectOffset
8518
+ }
8519
+ ] : []
8520
+ );
8521
+ return ranges.length === snapshot.ranges.length && ranges.every((range, index) => {
8522
+ const expected = snapshot.ranges[index];
8523
+ return expected !== void 0 && range.kind === expected.kind && range.indirectBufferIdentity === expected.indirectBufferIdentity && range.indirectOffset === expected.indirectOffset;
8524
+ });
8525
+ }
8526
+ function sameIndirectParameters(recording, parameters) {
8527
+ const expected = recording.passes.flatMap(
8528
+ (pass) => pass.ranges.map((range) => ({ pass: pass.pass, ...range }))
8529
+ );
8530
+ return expected.length === parameters.length && expected.every((range, index) => {
8531
+ const actual = parameters[index];
8532
+ 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;
8533
+ });
8534
+ }
8535
+ var SurfaceSubmissionCandidate = class {
8536
+ constructor(owner, sequence, frameId, requestedLane, deviceGeneration, viewIdentity, resourceGeneration) {
8537
+ this.owner = owner;
8538
+ this.sequence = sequence;
8539
+ this.frameId = frameId;
8540
+ this.requestedLane = requestedLane;
8541
+ this.deviceGeneration = deviceGeneration;
8542
+ this.viewIdentity = viewIdentity;
8543
+ this.resolvedResourceGeneration = resourceGeneration;
8544
+ }
8545
+ owner;
8546
+ sequence;
8547
+ frameId;
8548
+ requestedLane;
8549
+ deviceGeneration;
8550
+ viewIdentity;
8551
+ passes = /* @__PURE__ */ new Map();
8552
+ state = "recording";
8553
+ resolvedResourceGeneration;
8554
+ actualLaneReason;
8555
+ setResourceGeneration(generation) {
8556
+ if (this.state === "recording") this.resolvedResourceGeneration = generation;
8557
+ }
8558
+ get resourceGeneration() {
8559
+ return this.resolvedResourceGeneration;
8560
+ }
8561
+ setActualLaneReason(reason) {
8562
+ if (this.state === "recording") this.actualLaneReason = reason;
8563
+ }
8564
+ record(pass, command) {
8565
+ if (this.state !== "recording") return;
8566
+ let recording = this.passes.get(pass);
8567
+ if (recording === void 0) {
8568
+ recording = { commands: [], totalCommandCount: 0, sawIndirect: false };
8569
+ this.passes.set(pass, recording);
8570
+ }
8571
+ recording.totalCommandCount += 1;
8572
+ recording.sawIndirect ||= isIndirect(command);
8573
+ if (recording.commands.length >= MAX_COMMANDS_PER_PASS) return;
8574
+ const programEvidence = command.receiptIdentity === void 0 || command.receiptGeneration === void 0 ? "missing" : "producer-receipt";
8575
+ recording.commands.push(Object.freeze({ ...command, programEvidence }));
8576
+ }
8577
+ /** Snapshot consumed only by the readback copy encoded for this candidate. */
8578
+ gpuReadbackSnapshot() {
8579
+ if (this.state !== "submitted") return void 0;
8580
+ const passes = ["nearest-layer", "color"].flatMap((pass) => {
8581
+ const recording = this.passes.get(pass);
8582
+ if (recording === void 0) return [];
8583
+ if (!recording.sawIndirect) return [];
8584
+ const ranges = recording.commands.flatMap(
8585
+ (command) => isIndirect(command) ? [
8586
+ Object.freeze({
8587
+ kind: command.kind,
8588
+ indirectBufferIdentity: command.indirectBufferIdentity,
8589
+ indirectOffset: command.indirectOffset
8590
+ })
8591
+ ] : []
8592
+ );
8593
+ const savedCommandCount = recording.commands.length;
8594
+ return [
8595
+ Object.freeze({
8596
+ pass,
8597
+ totalCommandCount: recording.totalCommandCount,
8598
+ savedCommandCount,
8599
+ droppedCommandCount: recording.totalCommandCount - savedCommandCount,
8600
+ truncated: recording.totalCommandCount > savedCommandCount,
8601
+ ranges: Object.freeze(ranges)
8602
+ })
8603
+ ];
8604
+ });
8605
+ return Object.freeze({
8606
+ sequence: this.sequence,
8607
+ frameId: this.frameId,
8608
+ deviceGeneration: this.deviceGeneration,
8609
+ resourceGeneration: this.resourceGeneration,
8610
+ viewIdentity: this.viewIdentity,
8611
+ passes: Object.freeze(passes)
8612
+ });
8613
+ }
8614
+ get laneReason() {
8615
+ return this.actualLaneReason;
8616
+ }
8617
+ submit(completed, graphGeneration) {
8618
+ if (this.state !== "recording") return;
8619
+ this.state = "submitted";
8620
+ this.owner.submit(this, completed, graphGeneration, this.passes);
8621
+ }
8622
+ abort() {
8623
+ if (this.state === "recording") this.state = "aborted";
8624
+ }
8625
+ };
8626
+ var SurfaceSubmissionObservationOwner = class {
8627
+ constructor(currentDeviceGeneration) {
8628
+ this.currentDeviceGeneration = currentDeviceGeneration;
8629
+ }
8630
+ currentDeviceGeneration;
8631
+ sequence = 0;
8632
+ acceptedSequence = 0;
8633
+ latest;
8634
+ begin(input) {
8635
+ this.sequence += 1;
8636
+ return new SurfaceSubmissionCandidate(
8637
+ this,
8638
+ this.sequence,
8639
+ input.frameId,
8640
+ input.requestedLane,
8641
+ input.deviceGeneration,
8642
+ "main:0",
8643
+ input.resourceGeneration
8644
+ );
8645
+ }
8646
+ inspect() {
8647
+ return this.latest;
8648
+ }
8649
+ /** Attach only selector-visible members copied for this exact completed recording. */
8650
+ publishGpuMembers(readback, targetOrLegacyMembers) {
8651
+ const target = targetOrLegacyMembers === void 0 || Array.isArray(targetOrLegacyMembers) ? void 0 : targetOrLegacyMembers;
8652
+ if (typeof readback === "number" || target === void 0) return;
8653
+ const latest = this.latest;
8654
+ const recording = readback.recording;
8655
+ 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) => {
8656
+ const snapshot = recording.passes[index];
8657
+ return snapshot !== void 0 && sameReadbackPass(pass, snapshot);
8658
+ })) {
8659
+ return;
8660
+ }
8661
+ if (readback.indirectParameters === void 0 || !sameIndirectParameters(recording, readback.indirectParameters)) {
8662
+ return;
8663
+ }
8664
+ this.latest = Object.freeze({
8665
+ ...latest,
8666
+ passes: Object.freeze(
8667
+ latest.passes.map((pass) => {
8668
+ const passParameters = readback.indirectParameters?.filter(
8669
+ (parameter) => parameter.pass === pass.pass
8670
+ );
8671
+ return Object.freeze({
8672
+ ...pass,
8673
+ memberEvidence: readback.indirectParameters === void 0 ? "indirect-readback-required" : pass.truncated ? "indirect-visible-readback-truncated" : "indirect-visible-readback",
8674
+ memberIds: Object.freeze([...readback.memberIds]),
8675
+ ...pass.truncated || passParameters === void 0 ? {} : { indirectParameters: Object.freeze(passParameters) }
8676
+ });
8677
+ })
8678
+ )
8679
+ });
8680
+ }
8681
+ submit(candidate, completed, graphGeneration, recordings) {
8682
+ const sequence = candidate.sequence;
8683
+ const passes = ["nearest-layer", "color"].flatMap((pass) => {
8684
+ const recording = recordings.get(pass);
8685
+ if (recording === void 0 || recording.totalCommandCount === 0) return [];
8686
+ const savedCommandCount = recording.commands.length;
8687
+ const truncated = recording.totalCommandCount > savedCommandCount;
8688
+ return [
8689
+ Object.freeze({
8690
+ pass,
8691
+ commandCount: recording.totalCommandCount,
8692
+ totalCommandCount: recording.totalCommandCount,
8693
+ savedCommandCount,
8694
+ droppedCommandCount: recording.totalCommandCount - savedCommandCount,
8695
+ truncated,
8696
+ memberEvidence: recording.sawIndirect ? "indirect-readback-required" : truncated ? "direct-command-members-truncated" : "direct-command-members",
8697
+ commands: Object.freeze([...recording.commands])
8698
+ })
8699
+ ];
8700
+ });
8701
+ if (passes.length === 0) return;
8702
+ const actualLane = [...recordings.values()].some((recording) => recording.sawIndirect) ? "gpu-driven" : "direct";
8703
+ const submitted = Object.freeze({
8704
+ sequence,
8705
+ frameId: candidate.frameId,
8706
+ requestedLane: candidate.requestedLane,
8707
+ actualLane,
8708
+ ...candidate.laneReason === void 0 ? {} : { actualLaneReason: candidate.laneReason },
8709
+ deviceGeneration: candidate.deviceGeneration,
8710
+ graphGeneration,
8711
+ viewIdentity: candidate.viewIdentity,
8712
+ resourceGeneration: candidate.resourceGeneration,
8713
+ status: "submitted",
8714
+ passes: Object.freeze(passes)
8715
+ });
8716
+ this.latest = submitted;
8717
+ void completed.then(
8718
+ () => {
8719
+ if (sequence !== this.sequence || sequence < this.acceptedSequence || this.currentDeviceGeneration() !== candidate.deviceGeneration) {
8720
+ return;
8721
+ }
8722
+ this.acceptedSequence = sequence;
8723
+ this.latest = Object.freeze({ ...submitted, status: "completed" });
8724
+ },
8725
+ () => void 0
8726
+ );
8727
+ }
8728
+ };
8729
+
8730
+ // src/gpu-driven/resource-allocation.ts
8731
+ var GpuResourceAllocationLedger = class {
8732
+ nextId = 1;
8733
+ live = /* @__PURE__ */ new Map();
8734
+ pending = /* @__PURE__ */ new Map();
8735
+ liveBytes = 0;
8736
+ pendingBytes = 0;
8737
+ peakBytes = 0;
8738
+ successfulAllocationCount = 0;
8739
+ successfulAllocationBytes = 0;
8740
+ retiredBytes = 0;
8741
+ failedAllocationRollbacks = 0;
8742
+ failedAllocationRollbackBytes = 0;
8743
+ allocate(bytes) {
8744
+ if (!Number.isFinite(bytes) || bytes < 0) {
8745
+ throw new RangeError(`GPU allocation bytes must be finite and non-negative (got ${bytes})`);
8746
+ }
8747
+ const token = { id: this.nextId++, bytes };
8748
+ this.live.set(token.id, token.bytes);
8749
+ this.liveBytes += token.bytes;
8750
+ this.successfulAllocationCount += 1;
8751
+ this.successfulAllocationBytes += token.bytes;
8752
+ this.updatePeak();
8753
+ return token;
8754
+ }
8755
+ retire(token) {
8756
+ const bytes = this.live.get(token.id);
8757
+ if (bytes === void 0) return;
8758
+ this.live.delete(token.id);
8759
+ this.liveBytes -= bytes;
8760
+ this.pending.set(token.id, bytes);
8761
+ this.pendingBytes += bytes;
8762
+ this.updatePeak();
8763
+ }
8764
+ release(token) {
8765
+ const pendingBytes = this.pending.get(token.id);
8766
+ if (pendingBytes !== void 0) {
8767
+ this.pending.delete(token.id);
8768
+ this.pendingBytes -= pendingBytes;
8769
+ this.retiredBytes += pendingBytes;
8770
+ return;
8771
+ }
8772
+ const liveBytes = this.live.get(token.id);
8773
+ if (liveBytes !== void 0) {
8774
+ this.live.delete(token.id);
8775
+ this.liveBytes -= liveBytes;
8776
+ this.retiredBytes += liveBytes;
8777
+ }
8778
+ }
8779
+ rollback(token) {
8780
+ const bytes = this.live.get(token.id);
8781
+ if (bytes === void 0) return;
8782
+ this.live.delete(token.id);
8783
+ this.liveBytes -= bytes;
8784
+ this.failedAllocationRollbacks += 1;
8785
+ this.failedAllocationRollbackBytes += bytes;
8786
+ }
8787
+ inspect() {
8788
+ return {
8789
+ unit: "engine-allocation-bytes",
8790
+ physicalResidency: "unknown",
8791
+ liveBytes: this.liveBytes,
8792
+ pendingRetirementBytes: this.pendingBytes,
8793
+ peakBytes: this.peakBytes,
8794
+ successfulAllocationCount: this.successfulAllocationCount,
8795
+ successfulAllocationBytes: this.successfulAllocationBytes,
8796
+ pendingRetirementCount: this.pending.size,
8797
+ retiredBytes: this.retiredBytes,
8798
+ failedAllocationRollbacks: this.failedAllocationRollbacks,
8799
+ failedAllocationRollbackBytes: this.failedAllocationRollbackBytes
8800
+ };
8801
+ }
8802
+ updatePeak() {
8803
+ this.peakBytes = Math.max(this.peakBytes, this.liveBytes + this.pendingBytes);
8804
+ }
8805
+ };
8806
+ function combineGpuResourceAllocationInspections(inspections) {
8807
+ if (inspections.length === 0) return void 0;
8808
+ const liveBytes = inspections.reduce((sum, value) => sum + value.liveBytes, 0);
8809
+ const pendingRetirementBytes = inspections.reduce(
8810
+ (sum, value) => sum + value.pendingRetirementBytes,
8811
+ 0
8812
+ );
8813
+ const peakBytes = Math.max(
8814
+ liveBytes + pendingRetirementBytes,
8815
+ ...inspections.map((value) => value.peakBytes)
8816
+ );
8817
+ return {
8818
+ unit: "engine-allocation-bytes",
8819
+ physicalResidency: "unknown",
8820
+ liveBytes,
8821
+ pendingRetirementBytes,
8822
+ peakBytes,
8823
+ successfulAllocationCount: inspections.reduce(
8824
+ (sum, value) => sum + value.successfulAllocationCount,
8825
+ 0
8826
+ ),
8827
+ successfulAllocationBytes: inspections.reduce(
8828
+ (sum, value) => sum + value.successfulAllocationBytes,
8829
+ 0
8830
+ ),
8831
+ pendingRetirementCount: inspections.reduce(
8832
+ (sum, value) => sum + value.pendingRetirementCount,
8833
+ 0
8834
+ ),
8835
+ retiredBytes: inspections.reduce((sum, value) => sum + value.retiredBytes, 0),
8836
+ failedAllocationRollbacks: inspections.reduce(
8837
+ (sum, value) => sum + value.failedAllocationRollbacks,
8838
+ 0
8839
+ ),
8840
+ failedAllocationRollbackBytes: inspections.reduce(
8841
+ (sum, value) => sum + value.failedAllocationRollbackBytes,
8842
+ 0
8843
+ )
8844
+ };
8845
+ }
8134
8846
 
8135
8847
  // src/scene/visibility/occlusion-confidence.ts
8136
8848
  function createConfidenceState() {
@@ -8482,6 +9194,7 @@ var COUNTER_WORDS = 2 + LOD_ROW_CAPACITY + 2;
8482
9194
  var GEOMETRY_WORK_COUNTER_OFFSET = 2 + LOD_ROW_CAPACITY;
8483
9195
  var ROOT_GEOMETRY_WORK_COUNTER_OFFSET = GEOMETRY_WORK_COUNTER_OFFSET + 1;
8484
9196
  var COUNTER_STRIDE = COUNTER_WORDS * 4;
9197
+ var INDIRECT_COMMAND_BYTES = 20;
8485
9198
  function selectGpuLodLane(caps) {
8486
9199
  return caps.compute && caps.storageBuffer && caps.indirectDrawing ? "gpu" : "cpu";
8487
9200
  }
@@ -8598,7 +9311,7 @@ fn selectLodLevel(
8598
9311
  @group(0) @binding(4) var<storage, read> batches: array<BatchRecord>;
8599
9312
  @group(0) @binding(5) var<uniform> view: ViewConstants;
8600
9313
  @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>>;
9314
+ @group(0) @binding(7) var<storage, read_write> visibleIndices: array<vec4<u32>>;
8602
9315
  @group(0) @binding(8) var<storage, read_write> indirectArgs: array<u32>;
8603
9316
 
8604
9317
  fn counterIndex(batchIndex: u32) -> u32 { return batchIndex * ${COUNTER_WORDS}u; }
@@ -8683,9 +9396,11 @@ fn cullView(@builtin(global_invocation_id) id: vec3<u32>) {
8683
9396
  if ((candidate.materialSlot & 0x80000000u) != 0u) {
8684
9397
  materialOrPalette = instance.customDataStart;
8685
9398
  }
8686
- visibleIndices[candidate.visibleBase + localVisible] = vec2<u32>(
9399
+ visibleIndices[candidate.visibleBase + localVisible] = vec4<u32>(
8687
9400
  candidate.submitAdmission >> 1u,
8688
9401
  materialOrPalette,
9402
+ candidate.primitiveIndex + 1u,
9403
+ candidate.generation,
8689
9404
  );
8690
9405
  }
8691
9406
 
@@ -8708,10 +9423,22 @@ fn finalizeView(@builtin(global_invocation_id) id: vec3<u32>) {
8708
9423
  let candidate = candidates[batch.candidateBase];
8709
9424
  let selectedLod = selectLodLevel(candidate.projectedHeight, candidate.previousLevel, candidate.historyValid != 0u, candidate.lodRows, candidate.lodCount);
8710
9425
  let lod = candidate.lodRows[selectedLod];
8711
- indirectArgs[args] = select(batch.count, lod.indexCount, candidate.lodCount > 0u);
9426
+ var drawCount = batch.count;
9427
+ var drawFirst = batch.first;
9428
+ var drawBaseVertex: i32 = 0;
9429
+ if (candidate.lodCount > 0u) {
9430
+ drawCount = lod.indexCount;
9431
+ if (batch.indexed != 0u) {
9432
+ drawFirst = lod.firstIndex;
9433
+ drawBaseVertex = lod.baseVertex;
9434
+ }
9435
+ } else if (batch.indexed != 0u) {
9436
+ drawBaseVertex = batch.baseVertex;
9437
+ }
9438
+ indirectArgs[args] = drawCount;
8712
9439
  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);
9440
+ indirectArgs[args + 2u] = drawFirst;
9441
+ indirectArgs[args + 3u] = bitcast<u32>(drawBaseVertex);
8715
9442
  indirectArgs[args + 4u] = 0u;
8716
9443
  }
8717
9444
  `
@@ -8773,6 +9500,8 @@ var GpuDrivenView = class _GpuDrivenView {
8773
9500
  bindGroupCreates = 0;
8774
9501
  bufferRebuilds = 0;
8775
9502
  resourceGeneration = 0;
9503
+ allocationLedger = new GpuResourceAllocationLedger();
9504
+ allocationTokens = /* @__PURE__ */ new WeakMap();
8776
9505
  /** The last readback copy that was actually encoded and is not consumed. */
8777
9506
  telemetryPending;
8778
9507
  /** Receipt identity for the copy pass encoded by the current frame. */
@@ -9013,7 +9742,8 @@ var GpuDrivenView = class _GpuDrivenView {
9013
9742
  viewConstantsUploadBytes: this.viewConstantsUploadBytes,
9014
9743
  bindGroupCreates: this.bindGroupCreates,
9015
9744
  bufferRebuilds: this.bufferRebuilds,
9016
- resourceGeneration: this.resourceGeneration
9745
+ resourceGeneration: this.resourceGeneration,
9746
+ resourceAllocation: this.allocationLedger.inspect()
9017
9747
  };
9018
9748
  }
9019
9749
  get visibleBuffer() {
@@ -9058,6 +9788,7 @@ var GpuDrivenView = class _GpuDrivenView {
9058
9788
  let overflow = false;
9059
9789
  let geometryWork = 0;
9060
9790
  let rootGeometryWork = 0;
9791
+ const actualMembers = [];
9061
9792
  const histogram = /* @__PURE__ */ new Map();
9062
9793
  for (let batchIndex = 0; batchIndex < plan.batches.length; batchIndex += 1) {
9063
9794
  const offset = batchIndex * COUNTER_STRIDE;
@@ -9066,6 +9797,26 @@ var GpuDrivenView = class _GpuDrivenView {
9066
9797
  values.getUint32(offset, true),
9067
9798
  plan.batches[batchIndex]?.visibleCapacity ?? 0
9068
9799
  );
9800
+ const batch = plan.batches[batchIndex];
9801
+ const admitted = batch?.candidates.filter(
9802
+ (candidate) => candidate.submitAdmission !== false
9803
+ ) ?? [];
9804
+ for (let visibleIndex = 0; visibleIndex < batchVisible; visibleIndex += 1) {
9805
+ const visibleOffset = this.batchCapacity * COUNTER_STRIDE + ((batch?.visibleBase ?? 0) + visibleIndex) * 16;
9806
+ const projectionIndex = values.getUint32(visibleOffset, true);
9807
+ const primitiveIndex = values.getUint32(visibleOffset + 8, true) - 1;
9808
+ const generation = values.getUint32(visibleOffset + 12, true);
9809
+ const candidate = admitted[projectionIndex];
9810
+ if (batch !== void 0 && candidate !== void 0 && candidate.primitiveIndex === primitiveIndex && candidate.generation === generation) {
9811
+ actualMembers.push({
9812
+ batchId: batch.batchId,
9813
+ primitiveIndex,
9814
+ generation,
9815
+ drawItemIndex: candidate.drawItemIndex,
9816
+ instanceOrdinal: candidate.instanceOrdinal
9817
+ });
9818
+ }
9819
+ }
9069
9820
  visible += batchVisible;
9070
9821
  overflow ||= batchOverflow;
9071
9822
  geometryWork += values.getUint32(offset + GEOMETRY_WORK_COUNTER_OFFSET * 4, true);
@@ -9079,7 +9830,16 @@ var GpuDrivenView = class _GpuDrivenView {
9079
9830
  return void 0;
9080
9831
  }
9081
9832
  const candidateCount = plan.candidateCount;
9833
+ const surfaceReadback = copy.surfaceReadbackSnapshot?.();
9834
+ const surfaceIndirectReadback = surfaceReadback === void 0 ? void 0 : decodeSurfaceIndirectParameters({
9835
+ bytes: range.value,
9836
+ byteOffset: copy.indirectReadbackOffset,
9837
+ byteLength: this.indirectCapacity * INDIRECT_COMMAND_BYTES,
9838
+ indirectBufferIdentity: copy.indirectBufferIdentity,
9839
+ recording: surfaceReadback
9840
+ });
9082
9841
  this.lodSelection = Object.freeze({
9842
+ resourceGeneration: copy.resourceGeneration,
9083
9843
  candidateCount,
9084
9844
  batchCount: plan.batches.length,
9085
9845
  // Selector-only batches remain in the plan/readback but the production
@@ -9121,6 +9881,9 @@ var GpuDrivenView = class _GpuDrivenView {
9121
9881
  ),
9122
9882
  geometryWork,
9123
9883
  rootGeometryWork,
9884
+ actualMembers: Object.freeze(actualMembers),
9885
+ ...surfaceReadback === void 0 ? {} : { surfaceReadback },
9886
+ ...surfaceIndirectReadback === void 0 ? {} : surfaceIndirectReadback.ok ? { surfaceIndirectParameters: surfaceIndirectReadback.value } : { surfaceIndirectReadbackError: surfaceIndirectReadback.error },
9124
9887
  ...copy.submit === void 0 ? {} : { submit: copy.submit }
9125
9888
  });
9126
9889
  this.telemetryPending = void 0;
@@ -9129,7 +9892,7 @@ var GpuDrivenView = class _GpuDrivenView {
9129
9892
  mapped.value.unmap();
9130
9893
  }
9131
9894
  }
9132
- addPasses(builder, labelPrefix = "gpu-driven", includeCompute = true) {
9895
+ addPasses(builder, labelPrefix = "gpu-driven", includeCompute = true, surfaceSubmissionObservation) {
9133
9896
  const buffers = this.buffers;
9134
9897
  const bindGroup = this.bindGroup;
9135
9898
  const plan = this.plan;
@@ -9209,14 +9972,14 @@ var GpuDrivenView = class _GpuDrivenView {
9209
9972
  const lodReadback = importBuffer(
9210
9973
  `${labelPrefix}.lod-selection-readback`,
9211
9974
  buffers.lodReadback,
9212
- this.batchCapacity * COUNTER_STRIDE,
9975
+ this.batchCapacity * COUNTER_STRIDE + this.visibleBufferCapacity * 16 + this.indirectCapacity * INDIRECT_COMMAND_BYTES,
9213
9976
  GPU_BUFFER_USAGE_MAP_READ | GPU_BUFFER_USAGE_COPY_DST
9214
9977
  );
9215
9978
  if (!lodReadback.ok) return lodReadback;
9216
9979
  const visible = importBuffer(
9217
9980
  `${labelPrefix}.visible`,
9218
9981
  buffers.visible,
9219
- this.visibleBufferCapacity * 8,
9982
+ this.visibleBufferCapacity * 16,
9220
9983
  GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC
9221
9984
  );
9222
9985
  if (!visible.ok) return visible;
@@ -9282,9 +10045,13 @@ var GpuDrivenView = class _GpuDrivenView {
9282
10045
  });
9283
10046
  if (!finalize.ok) return finalize;
9284
10047
  const graphResourceGeneration = this.resourceGeneration;
10048
+ const indirectReadbackOffset = this.batchCapacity * COUNTER_STRIDE + this.visibleBufferCapacity * 16;
10049
+ const indirectBufferIdentity = getOpaqueResourceIdentity(buffers.indirect);
9285
10050
  const readback = builder.addCopyPass(`${labelPrefix}.lod-selection-readback`, {
9286
10051
  accesses: [
9287
10052
  { resource: counters.value, usage: "copy-src" },
10053
+ { resource: visible.value, usage: "copy-src" },
10054
+ { resource: indirect.value, usage: "copy-src" },
9288
10055
  { resource: lodReadback.value, usage: "copy-dst" }
9289
10056
  ],
9290
10057
  encode: ({ encoder, resources }) => {
@@ -9295,12 +10062,32 @@ var GpuDrivenView = class _GpuDrivenView {
9295
10062
  resources.buffer(lodReadback.value).unwrap(),
9296
10063
  this.batchCapacity * COUNTER_STRIDE
9297
10064
  );
10065
+ encoder.copyBufferToBuffer(
10066
+ resources.buffer(visible.value).unwrap(),
10067
+ 0,
10068
+ resources.buffer(lodReadback.value).unwrap(),
10069
+ this.batchCapacity * COUNTER_STRIDE,
10070
+ this.visibleBufferCapacity * 16
10071
+ );
10072
+ encoder.copyBufferToBuffer(
10073
+ resources.buffer(indirect.value).unwrap(),
10074
+ 0,
10075
+ resources.buffer(lodReadback.value).unwrap(),
10076
+ indirectReadbackOffset,
10077
+ this.indirectCapacity * INDIRECT_COMMAND_BYTES
10078
+ );
9298
10079
  const submittedPlan = this.plan;
9299
10080
  if (this.buffers === buffers && submittedPlan !== void 0 && this.resourceGeneration === graphResourceGeneration) {
10081
+ const submittedObservation = surfaceSubmissionObservation?.();
9300
10082
  this.telemetryPending = {
9301
10083
  buffers,
9302
10084
  plan: submittedPlan,
9303
10085
  resourceGeneration: graphResourceGeneration,
10086
+ indirectBufferIdentity,
10087
+ indirectReadbackOffset,
10088
+ ...submittedObservation === void 0 ? {} : {
10089
+ surfaceReadbackSnapshot: () => submittedObservation.gpuReadbackSnapshot()
10090
+ },
9304
10091
  ...this.telemetrySubmit === void 0 ? {} : { submit: this.telemetrySubmit }
9305
10092
  };
9306
10093
  }
@@ -9336,6 +10123,7 @@ var GpuDrivenView = class _GpuDrivenView {
9336
10123
  this.telemetrySubmit = void 0;
9337
10124
  this.lodSelectionReadback = void 0;
9338
10125
  this.lodSelection = void 0;
10126
+ for (const generation of buffers) this.retireGeneration(generation);
9339
10127
  this.destroyAfterSubmittedWork(buffers);
9340
10128
  void this.pipelineLayout;
9341
10129
  }
@@ -9372,6 +10160,7 @@ var GpuDrivenView = class _GpuDrivenView {
9372
10160
  const nextBatch = nextCapacity(batchCapacity);
9373
10161
  const nextIndirect = nextCapacity(indirectCapacity);
9374
10162
  const created = {};
10163
+ const createdTokens = [];
9375
10164
  const allocate = (name, size, usage) => {
9376
10165
  const buffer = this.device.createBuffer({
9377
10166
  label: `gpu-driven-view-${name}`,
@@ -9381,6 +10170,9 @@ var GpuDrivenView = class _GpuDrivenView {
9381
10170
  });
9382
10171
  if (!buffer.ok) return buffer;
9383
10172
  created[name] = buffer.value;
10173
+ const token = this.allocationLedger.allocate(size);
10174
+ this.allocationTokens.set(buffer.value, token);
10175
+ createdTokens.push(token);
9384
10176
  return ok$1(void 0);
9385
10177
  };
9386
10178
  const storage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC;
@@ -9404,7 +10196,7 @@ var GpuDrivenView = class _GpuDrivenView {
9404
10196
  storage: false
9405
10197
  },
9406
10198
  { name: "counters", size: nextBatch * COUNTER_STRIDE, usage: storage, storage: true },
9407
- { name: "visible", size: nextVisible * 8, usage: storage, storage: true },
10199
+ { name: "visible", size: nextVisible * 16, usage: storage, storage: true },
9408
10200
  {
9409
10201
  name: "indirect",
9410
10202
  size: nextIndirect * 20,
@@ -9413,7 +10205,7 @@ var GpuDrivenView = class _GpuDrivenView {
9413
10205
  },
9414
10206
  {
9415
10207
  name: "lodReadback",
9416
- size: nextBatch * COUNTER_STRIDE,
10208
+ size: nextBatch * COUNTER_STRIDE + nextVisible * 16 + nextIndirect * INDIRECT_COMMAND_BYTES,
9417
10209
  usage: GPU_BUFFER_USAGE_MAP_READ | GPU_BUFFER_USAGE_COPY_DST,
9418
10210
  storage: false
9419
10211
  }
@@ -9439,10 +10231,14 @@ var GpuDrivenView = class _GpuDrivenView {
9439
10231
  const result = allocate(request.name, request.size, request.usage);
9440
10232
  if (!result.ok) {
9441
10233
  for (const buffer of Object.values(created)) this.device.destroyBuffer(buffer);
10234
+ for (const token of createdTokens) this.allocationLedger.rollback(token);
9442
10235
  return result;
9443
10236
  }
9444
10237
  }
9445
- if (this.buffers !== void 0) this.supersededBuffers.push(this.buffers);
10238
+ if (this.buffers !== void 0) {
10239
+ this.supersededBuffers.push(this.buffers);
10240
+ this.retireGeneration(this.buffers);
10241
+ }
9446
10242
  this.buffers = created;
9447
10243
  this.candidateCapacity = nextCandidate;
9448
10244
  this.visibleBufferCapacity = nextVisible;
@@ -9459,11 +10255,19 @@ var GpuDrivenView = class _GpuDrivenView {
9459
10255
  for (const buffers of generations) {
9460
10256
  for (const buffer of Object.values(buffers)) {
9461
10257
  this.device.destroyBuffer(buffer);
10258
+ const token = this.allocationTokens.get(buffer);
10259
+ if (token !== void 0) this.allocationLedger.release(token);
9462
10260
  }
9463
10261
  }
9464
10262
  };
9465
10263
  void this.device.queue.onSubmittedWorkDone().then(release, release);
9466
10264
  }
10265
+ retireGeneration(generation) {
10266
+ for (const buffer of Object.values(generation)) {
10267
+ const token = this.allocationTokens.get(buffer);
10268
+ if (token !== void 0) this.allocationLedger.retire(token);
10269
+ }
10270
+ }
9467
10271
  };
9468
10272
 
9469
10273
  // src/gpu-driven/shadow-views.ts
@@ -9891,6 +10695,7 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
9891
10695
  );
9892
10696
  }
9893
10697
  const projectorAvailable = pipelineState.projectorAvailable !== false;
10698
+ const lowLimitCloudBindings = !extendedLighting && !projectorAvailable;
9894
10699
  try {
9895
10700
  return getOrCreateFromChain(
9896
10701
  frameState.viewBindGroupCache,
@@ -9903,7 +10708,8 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
9903
10708
  pipelineState.shadowCasterCascadeBuffer,
9904
10709
  pipelineState.shadowFallbackTextureView,
9905
10710
  ...extendedLighting ? extendedLightingCacheKeys : projectorAvailable ? [pipelineState.defaultWhiteTextureView, pipelineState.defaultSampler] : [],
9906
- pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer
10711
+ pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
10712
+ ...lowLimitCloudBindings ? [] : [pipelineState.defaultWhiteTextureView, pipelineState.defaultSampler]
9907
10713
  ],
9908
10714
  variant,
9909
10715
  () => {
@@ -9979,7 +10785,23 @@ function ensureTypedShadowViewBg(c, viewOffset, cascadeOffset, variant) {
9979
10785
  binding: 12,
9980
10786
  resource: { kind: "sampler", value: pipelineState.defaultSampler }
9981
10787
  }
9982
- ] : []
10788
+ ] : [],
10789
+ ...lowLimitCloudBindings ? [] : [
10790
+ {
10791
+ binding: 16,
10792
+ resource: {
10793
+ kind: "textureView",
10794
+ value: pipelineState.defaultWhiteTextureView
10795
+ }
10796
+ },
10797
+ {
10798
+ binding: 17,
10799
+ resource: {
10800
+ kind: "sampler",
10801
+ value: pipelineState.defaultSampler
10802
+ }
10803
+ }
10804
+ ]
9983
10805
  ]
9984
10806
  });
9985
10807
  if (!created.ok) throw created.error;
@@ -10358,6 +11180,7 @@ function recordGpuDrivenShadowIfPublished(c, pass, identity) {
10358
11180
  visibleBindGroup: projection.visibleBindGroup,
10359
11181
  deformation: projection.deformation,
10360
11182
  materialGroup,
11183
+ ...batch.key.admission === "alpha-mask" ? { alphaMaskMaterialGroup: materialGroup } : {},
10361
11184
  vertexBuffer: projection.mesh.vertexBuffer.handle,
10362
11185
  ...batch.key.drawKind === "indexed" && projection.mesh.indexBuffer !== null ? {
10363
11186
  indexBuffer: projection.mesh.indexBuffer.handle,
@@ -11192,7 +12015,6 @@ function ensureSpotShadowMaterialBg(c) {
11192
12015
  prefilterView: fb.prefilterView,
11193
12016
  prefilterSampler: fb.sampler,
11194
12017
  brdfLutView: fb.brdfLutView,
11195
- brdfLutSampler: fb.sampler,
11196
12018
  intensityBuffer: fb.intensityBuffer
11197
12019
  },
11198
12020
  transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage) ? void 0 : null
@@ -11246,7 +12068,6 @@ function ensureGpuDrivenAlphaMaskMaterialBg(c, projection) {
11246
12068
  prefilterView: fallback.prefilterView,
11247
12069
  prefilterSampler: fallback.sampler,
11248
12070
  brdfLutView: fallback.brdfLutView,
11249
- brdfLutSampler: fallback.sampler,
11250
12071
  intensityBuffer: fallback.intensityBuffer
11251
12072
  };
11252
12073
  const deps = {
@@ -11272,7 +12093,10 @@ function ensureGpuDrivenAlphaMaskMaterialBg(c, projection) {
11272
12093
  return bindGroup;
11273
12094
  }
11274
12095
  function ensureGpuDrivenCustomShadowMaterialBg(c, projection) {
11275
- const shaderId = projection.shadowArtifact.material;
12096
+ const shaderId = projection.shadowArtifact.specializationKey ?? projection.shadowArtifact.material;
12097
+ const materialKey = `shadow-material-custom:${shaderId}:${projection.materialEntityKey}:${projection.material.materialHandle ?? -1}:${c.store.materialResourceEpoch}`;
12098
+ const cached = c.materialBgAssemblyCache.get(materialKey);
12099
+ if (cached !== void 0) return cached.bindGroup;
11276
12100
  const fallback = c.pipelineState.skylightFallback;
11277
12101
  if (fallback === null) {
11278
12102
  throw new RhiError({
@@ -11295,7 +12119,6 @@ function ensureGpuDrivenCustomShadowMaterialBg(c, projection) {
11295
12119
  prefilterView: fallback.prefilterView,
11296
12120
  prefilterSampler: fallback.sampler,
11297
12121
  brdfLutView: fallback.brdfLutView,
11298
- brdfLutSampler: fallback.sampler,
11299
12122
  intensityBuffer: fallback.intensityBuffer
11300
12123
  };
11301
12124
  const deps = {
@@ -11334,18 +12157,23 @@ function isTransmissionMaterial(material) {
11334
12157
  return material.materialShaderId === "forgeax::default-standard-pbr" && typeof material.paramSnapshot?.transmission === "number" && material.paramSnapshot.transmission > 0;
11335
12158
  }
11336
12159
  function matchesRecordMode(material, mode) {
12160
+ const medium = material.surfaceModel === "single-layer-medium" || material.materialShaderId === "forgeax::single-layer-medium";
12161
+ if (mode === "single-layer-medium-nearest-layer" || mode === "single-layer-medium-color") {
12162
+ return medium;
12163
+ }
11337
12164
  const transmission = isTransmissionMaterial(material);
11338
12165
  if (mode === "transmission") return transmission;
11339
- if (mode === "transparent") return material.transparent === true && !transmission;
11340
- return !transmission && material.transparent !== true;
12166
+ if (mode === "transparent") return material.transparent === true && !transmission && !medium;
12167
+ return !transmission && material.transparent !== true && !medium;
11341
12168
  }
11342
12169
  function matchedMaterialsForRecordMode(c, matchedMaterials, mode) {
11343
12170
  if (mode === void 0) return matchedMaterials;
12171
+ const surfaceMode = mode === "single-layer-medium-nearest-layer" || mode === "single-layer-medium-color";
11344
12172
  const filtered = /* @__PURE__ */ new Map();
11345
12173
  for (const entry of c.validatedOrdered) {
11346
12174
  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));
12175
+ if (!surfaceMode && matchedMaterials !== null && dispatchHandles === void 0) continue;
12176
+ const candidateHandles = surfaceMode ? entry.source.materials.map((material) => material.materialHandle ?? 0) : dispatchHandles ?? (mode === "transmission" ? [] : entry.source.materials.map((material) => material.materialHandle ?? 0));
11349
12177
  const handles = /* @__PURE__ */ new Set();
11350
12178
  for (const handle of candidateHandles) {
11351
12179
  const material = entry.source.materials.find((candidate) => (candidate.materialHandle ?? 0) === handle) ?? entry.source.material;
@@ -11388,11 +12216,14 @@ function recordMainPass(c, selector, options, graphPass) {
11388
12216
  const passKind = options?.passKind ?? "forward";
11389
12217
  const recordMode = options?.recordMode;
11390
12218
  const transmissionBackdropView = options?.transmissionBackdropView;
11391
- if (recordMode === "transmission" && transmissionBackdropView == null) {
12219
+ const surfaceRawDepthView = options?.surfaceRawDepthView;
12220
+ const surfaceNearestLayerView = options?.surfaceNearestLayerView;
12221
+ const surfaceNearestDepthView = options?.surfaceNearestDepthView;
12222
+ if ((recordMode === "transmission" || recordMode === "single-layer-medium-nearest-layer" || recordMode === "single-layer-medium-color") && transmissionBackdropView == null) {
11392
12223
  throw new RhiError({
11393
12224
  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"
12225
+ expected: "transmissionBackdropView != null for a backdrop-consuming record mode",
12226
+ hint: "the typed Standard backdrop pass must resolve its graph-paired color view"
11396
12227
  });
11397
12228
  }
11398
12229
  const colorViews = options?.colorViews ?? [geometryColorView];
@@ -11404,12 +12235,9 @@ function recordMainPass(c, selector, options, graphPass) {
11404
12235
  const videoHighPerfAvailable = probeVideoHighPerfUpload(runtime.device);
11405
12236
  const clusteredLighting = c.standardLighting?.kind === "clustered";
11406
12237
  const clusteredBindGroupMissing = validatedOrdered.length > 0 && !standardTopologyBindGroupReady(c.standardLighting, hdrpClusterBindGroup);
12238
+ const hdrpBuffers = clusteredLighting ? getOrCreateHdrpBuffers(runtime, frameState.installedPipelineConfig?.clusterGrid) : null;
11407
12239
  let hdrpSsaoBindGroup = null;
11408
- if (clusteredLighting && hdrpClusterBindGroup !== null && c.hdrpSsaoBlurredView !== void 0) {
11409
- const hdrpBuffers = getOrCreateHdrpBuffers(
11410
- runtime,
11411
- frameState.installedPipelineConfig?.clusterGrid
11412
- );
12240
+ if (hdrpClusterBindGroup !== null && c.hdrpSsaoBlurredView !== void 0) {
11413
12241
  if (hdrpBuffers !== null) {
11414
12242
  hdrpSsaoBindGroup = createHdrpUnifiedBindGroup(
11415
12243
  runtime,
@@ -11420,6 +12248,58 @@ function recordMainPass(c, selector, options, graphPass) {
11420
12248
  }
11421
12249
  }
11422
12250
  const meshGroup2 = clusteredLighting ? hdrpSsaoBindGroup ?? hdrpClusterBindGroup : meshBindGroup;
12251
+ if (gpuDrivenStandardPbrFrameResources !== void 0) {
12252
+ gpuDrivenStandardPbrFrameResources.clusterBindGroup = clusteredLighting && meshGroup2 !== null ? meshGroup2 : void 0;
12253
+ if (hdrpBuffers === null) {
12254
+ gpuDrivenStandardPbrFrameResources.clusterBindGroupForMesh = void 0;
12255
+ gpuDrivenStandardPbrFrameResources.clusterBindGroupForSkin = void 0;
12256
+ } else {
12257
+ const projectedGroups = /* @__PURE__ */ new Map();
12258
+ gpuDrivenStandardPbrFrameResources.clusterBindGroupForMesh = (meshBuffer, bindingBytes) => {
12259
+ const cached = projectedGroups.get(meshBuffer);
12260
+ if (cached !== void 0) return cached;
12261
+ const created = createHdrpUnifiedBindGroup(
12262
+ runtime,
12263
+ hdrpBuffers,
12264
+ meshBuffer,
12265
+ c.hdrpSsaoBlurredView === void 0 ? { enabled: false } : { enabled: true, ssaoBlurredView: c.hdrpSsaoBlurredView },
12266
+ bindingBytes
12267
+ );
12268
+ if (created !== null) projectedGroups.set(meshBuffer, created);
12269
+ return created ?? void 0;
12270
+ };
12271
+ const projectedSkinGroups = /* @__PURE__ */ new Map();
12272
+ gpuDrivenStandardPbrFrameResources.clusterBindGroupForSkin = (meshBuffer, meshBindingBytes, paletteBuffer, paletteBindingWindowBytes) => {
12273
+ let meshGroups = projectedSkinGroups.get(meshBuffer);
12274
+ if (meshGroups === void 0) {
12275
+ meshGroups = /* @__PURE__ */ new Map();
12276
+ projectedSkinGroups.set(meshBuffer, meshGroups);
12277
+ }
12278
+ let paletteGroups = meshGroups.get(paletteBuffer);
12279
+ if (paletteGroups === void 0) {
12280
+ paletteGroups = /* @__PURE__ */ new Map();
12281
+ meshGroups.set(paletteBuffer, paletteGroups);
12282
+ }
12283
+ const bindingKey = `${meshBindingBytes}:${paletteBindingWindowBytes}`;
12284
+ const cached = paletteGroups.get(bindingKey);
12285
+ if (cached !== void 0) return cached;
12286
+ const skinLayout = pipelineState.hdrpSkinMeshBindGroupLayout;
12287
+ if (skinLayout === null) return void 0;
12288
+ const created = createHdrpSkinUnifiedBindGroup(
12289
+ runtime,
12290
+ hdrpBuffers,
12291
+ skinLayout,
12292
+ meshBuffer,
12293
+ paletteBuffer,
12294
+ paletteBindingWindowBytes,
12295
+ c.hdrpSsaoBlurredView === void 0 ? { enabled: false } : { enabled: true, ssaoBlurredView: c.hdrpSsaoBlurredView },
12296
+ meshBindingBytes
12297
+ );
12298
+ if (created !== null) paletteGroups.set(bindingKey, created);
12299
+ return created ?? void 0;
12300
+ };
12301
+ }
12302
+ }
11423
12303
  let geometryPassEnded = false;
11424
12304
  const mainColorLoadOp = skyboxActive ? "load" : "clear";
11425
12305
  const mainPassResolves = passKind === "forward" && msaaActive && geometryColorResolveView !== null && !splitLdrSprite;
@@ -11500,7 +12380,7 @@ function recordMainPass(c, selector, options, graphPass) {
11500
12380
  identities: [
11501
12381
  getOpaqueResourceIdentity(skylightResources.irradianceSampler),
11502
12382
  getOpaqueResourceIdentity(skylightResources.prefilterSampler),
11503
- getOpaqueResourceIdentity(skylightResources.brdfLutSampler)
12383
+ getOpaqueResourceIdentity(skylightResources.irradianceSampler)
11504
12384
  ]
11505
12385
  },
11506
12386
  resources: {
@@ -11520,7 +12400,9 @@ function recordMainPass(c, selector, options, graphPass) {
11520
12400
  },
11521
12401
  brdfLut: {
11522
12402
  viewIdentity: getOpaqueResourceIdentity(skylightResources.brdfLutView),
11523
- samplerIdentity: getOpaqueResourceIdentity(skylightResources.brdfLutSampler),
12403
+ samplerIdentity: getOpaqueResourceIdentity(
12404
+ skylightResources.irradianceSampler
12405
+ ),
11524
12406
  deviceGeneration: runtime.deviceScope.generation
11525
12407
  },
11526
12408
  intensityBufferIdentity: getOpaqueResourceIdentity(
@@ -11565,7 +12447,6 @@ function recordMainPass(c, selector, options, graphPass) {
11565
12447
  skylightPrefilterView: skylightResources.prefilterView,
11566
12448
  prefilterSampler: row.sampler,
11567
12449
  brdfLutView: skylightResources.brdfLutView,
11568
- brdfLutSampler: skylightResources.brdfLutSampler,
11569
12450
  intensityBuffer: row.uniformBuffer
11570
12451
  };
11571
12452
  return { resources: probeResources, probeIndex: row.index };
@@ -11577,7 +12458,10 @@ function recordMainPass(c, selector, options, graphPass) {
11577
12458
  ...gpuDrivenStandardPbrFrameResources?.sceneMaterialBuffer === void 0 && gpuDrivenSceneMaterialBuffer === void 0 ? {} : {
11578
12459
  sceneMaterialBuffer: gpuDrivenStandardPbrFrameResources?.sceneMaterialBuffer ?? gpuDrivenSceneMaterialBuffer
11579
12460
  },
11580
- ...transmissionBackdropView === void 0 ? {} : { transmissionBackdropView }
12461
+ ...transmissionBackdropView === void 0 ? {} : { transmissionBackdropView },
12462
+ ...surfaceRawDepthView === void 0 ? {} : { surfaceRawDepthView },
12463
+ ...surfaceNearestLayerView === void 0 ? {} : { surfaceNearestLayerView },
12464
+ ...surfaceNearestDepthView === void 0 ? {} : { surfaceNearestDepthView }
11581
12465
  };
11582
12466
  const buildPerSubmeshMaterialBg2 = (submeshMaterial, entityKey, materialWorld = world, materialShaderId = submeshMaterial.materialShaderId) => buildPerSubmeshMaterialBg(
11583
12467
  perSubmeshMaterialBgDeps,
@@ -11590,6 +12474,7 @@ function recordMainPass(c, selector, options, graphPass) {
11590
12474
  for (let materialSlot = 0; materialSlot < materialSlotCount; materialSlot += 1) {
11591
12475
  const material = materialSlots[materialSlot];
11592
12476
  if (material === void 0 || (material.videoTextureFields?.size ?? 0) > 0) continue;
12477
+ if (recordMode !== void 0 && !matchesRecordMode(material, recordMode)) continue;
11593
12478
  const owner = materialSlotOwners[materialSlot];
11594
12479
  if (owner === void 0) continue;
11595
12480
  preparedMaterialBindGroups[materialSlot] = buildPerSubmeshMaterialBg2(
@@ -11660,7 +12545,10 @@ function recordMainPass(c, selector, options, graphPass) {
11660
12545
  passKind,
11661
12546
  selectedDispatch,
11662
12547
  colorFormats,
11663
- options?.coverageOnly ?? false
12548
+ options?.coverageOnly ?? false,
12549
+ options?.fragmentEntryPoint,
12550
+ recordMode === "single-layer-medium-nearest-layer" ? "nearest-layer" : recordMode === "single-layer-medium-color" ? "color" : void 0,
12551
+ options?.transparentDepthWrite ?? false
11664
12552
  );
11665
12553
  };
11666
12554
  if (c.profilePhase === void 0) {
@@ -11680,7 +12568,7 @@ function recordMainPass(c, selector, options, graphPass) {
11680
12568
  hint: "publish the current frame view/light/shadow bind group before GPU raster"
11681
12569
  });
11682
12570
  }
11683
- if (gpuDrivenStandardPbrFrameResources === void 0) {
12571
+ if (gpuDrivenStandardPbrFrameResources === void 0 || gpuDrivenStandardPbrFrameResources.materialBindGroups.length === 0) {
11684
12572
  throw new RhiError({
11685
12573
  code: "rhi-not-available",
11686
12574
  expected: "complete main-pass Standard PBR material bind-group receipt",
@@ -11691,7 +12579,9 @@ function recordMainPass(c, selector, options, graphPass) {
11691
12579
  viewBindGroup,
11692
12580
  pass,
11693
12581
  options.gpuDriven.resources,
11694
- gpuDrivenStandardPbrFrameResources
12582
+ gpuDrivenStandardPbrFrameResources,
12583
+ options.gpuDrivenFilter,
12584
+ options?.fragmentEntryPoint
11695
12585
  );
11696
12586
  }
11697
12587
  if (passKind === "forward" && recordMode === void 0) {
@@ -12049,7 +12939,7 @@ function recordBloomCompositePass(_c, resolve, graphPass) {
12049
12939
  stageBloomEncode(_c);
12050
12940
  if (graphPass === void 0) pass.end();
12051
12941
  }
12052
- function recordFxaaPass(c, resolve, graphPass, paramsOverride) {
12942
+ function recordFxaaPass(c, resolve, graphPass, paramsOverride, graphOutputFormat) {
12053
12943
  const { runtime, pipelineState, encoder, camera, currentTexture } = c;
12054
12944
  const fxaaActive = camera.antialias === "fxaa";
12055
12945
  if (fxaaActive && pipelineState.perPassResources.fxaaPipeline !== null && pipelineState.perPassResources.fxaaBindGroupLayout !== null && pipelineState.perPassResources.fxaaSampler !== null && runtime.getPostProcessParamsBuffer !== void 0) {
@@ -12096,7 +12986,7 @@ function recordFxaaPass(c, resolve, graphPass, paramsOverride) {
12096
12986
  },
12097
12987
  c.bindGroupCounts
12098
12988
  );
12099
- const fxaaColorFormat = runtime.device.caps.storageBuffer ? pipelineState.format : pipelineState.colorAttachmentFormat;
12989
+ const fxaaColorFormat = graphPass !== void 0 && graphOutputFormat !== void 0 ? graphOutputFormat : runtime.device.caps.storageBuffer ? pipelineState.format : pipelineState.colorAttachmentFormat;
12100
12990
  let fxaaPass = graphPass;
12101
12991
  if (fxaaPass === void 0) {
12102
12992
  const fxaaOutputView = runtime.device.createTextureView(currentTexture, {
@@ -12115,7 +13005,19 @@ function recordFxaaPass(c, resolve, graphPass, paramsOverride) {
12115
13005
  )
12116
13006
  );
12117
13007
  }
12118
- fxaaPass.setPipeline(pipelineState.perPassResources.fxaaPipeline);
13008
+ let fxaaPipeline = pipelineState.perPassResources.fxaaPipeline;
13009
+ if (graphPass !== void 0 && graphOutputFormat !== void 0) {
13010
+ const entry = runtime.lookupPostProcess?.(FXAA_POST_PROCESS_ID);
13011
+ const rebuilt = entry === void 0 || runtime.getPostProcessPipeline === void 0 ? null : runtime.getPostProcessPipeline(
13012
+ FXAA_POST_PROCESS_ID,
13013
+ fxaaBglLayout,
13014
+ [graphOutputFormat],
13015
+ entry
13016
+ );
13017
+ if (rebuilt !== null) fxaaPipeline = rebuilt;
13018
+ }
13019
+ if (fxaaPipeline === null) return;
13020
+ fxaaPass.setPipeline(fxaaPipeline);
12119
13021
  fxaaPass.setBindGroup(0, fxaaBg);
12120
13022
  fxaaPass.draw(3, 1, 0, 0);
12121
13023
  if (graphPass === void 0) fxaaPass.end();
@@ -12146,8 +13048,8 @@ function postProcessSourceDigest(source) {
12146
13048
  function postProcessShaderPipelineLabel(identity, source) {
12147
13049
  return `post-process-${identity}-pso-${postProcessSourceDigest(source)}`;
12148
13050
  }
12149
- function postProcessShaderModuleLabel(identity, source) {
12150
- return `${postProcessShaderPipelineLabel(identity, source)}-module`;
13051
+ function postProcessShaderModuleLabel(source) {
13052
+ return `post-process-module-${postProcessSourceDigest(source)}`;
12151
13053
  }
12152
13054
  function postProcessShaderEntrySignature(entry) {
12153
13055
  return JSON.stringify({
@@ -12157,7 +13059,9 @@ function postProcessShaderEntrySignature(entry) {
12157
13059
  byteSize: entry.params.byteSize,
12158
13060
  defaultValue: Array.from(entry.params.defaultValue)
12159
13061
  },
12160
- reads: entry.reads
13062
+ reads: entry.reads,
13063
+ usesView: entry.usesView,
13064
+ storageBindings: entry.storageBindings
12161
13065
  });
12162
13066
  }
12163
13067
  function isTemporalFullscreenBinding(values) {
@@ -12191,7 +13095,10 @@ var DEPTH_MIN_PARAMS_BYTE_SIZE = 16;
12191
13095
  function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12192
13096
  const { device } = ctx;
12193
13097
  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";
13098
+ const hasMultisampledColor = (entry.reads ?? []).some(
13099
+ (read) => typeof read !== "string" && read.sampleType === "multisampled-float"
13100
+ );
13101
+ 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
13102
  const descriptor = buildBindGroupLayoutDescriptor(FULLSCREEN_DEFAULT_SPEC, { kind: bglKind });
12196
13103
  const colorReads = (entry.reads ?? []).filter(
12197
13104
  (read) => typeof read === "string" || read.sampleType !== "depth"
@@ -12205,6 +13112,14 @@ function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12205
13112
  texture: { sampleType: "float", viewDimension: "2d" }
12206
13113
  });
12207
13114
  }
13115
+ const firstStorageBinding = firstExtraBinding + extraColorCount;
13116
+ for (const [index, binding] of (entry.storageBindings ?? []).entries()) {
13117
+ descriptor.entries.push({
13118
+ binding: binding ?? firstStorageBinding + index,
13119
+ visibility: GPU_SHADER_STAGE_FRAGMENT,
13120
+ buffer: { type: "read-only-storage" }
13121
+ });
13122
+ }
12208
13123
  const bglRes = device.createBindGroupLayout(descriptor);
12209
13124
  if (!bglRes.ok) {
12210
13125
  ctx.errorRegistry.fire(bglRes.error);
@@ -12219,6 +13134,9 @@ function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12219
13134
  extraColorBindings: Object.freeze(
12220
13135
  Array.from({ length: extraColorCount }, (_, index) => firstExtraBinding + index)
12221
13136
  ),
13137
+ extraStorageBindings: Object.freeze(
13138
+ (entry.storageBindings ?? []).map((binding, index) => binding ?? firstStorageBinding + index)
13139
+ ),
12222
13140
  createHandle: (name, pipeline, paramsBuffer) => ({
12223
13141
  name,
12224
13142
  paramsBuffer,
@@ -12229,7 +13147,7 @@ function buildFullscreenPostProcessPass(ctx, entry, depthMultisampled = false) {
12229
13147
  })
12230
13148
  };
12231
13149
  }
12232
- function createFullscreenBindGroup(device, bgl, inputView, sampler, paramsBuffer, depthTexView, depthSampler, additionalViews = []) {
13150
+ function createFullscreenBindGroup(device, bgl, inputView, sampler, paramsBuffer, depthTexView, depthSampler, additionalViews = [], additionalBuffers = []) {
12233
13151
  const entries = [
12234
13152
  { binding: 0, resource: { kind: "textureView", value: inputView } }
12235
13153
  ];
@@ -12249,6 +13167,12 @@ function createFullscreenBindGroup(device, bgl, inputView, sampler, paramsBuffer
12249
13167
  resource: { kind: "textureView", value: additional.view }
12250
13168
  });
12251
13169
  }
13170
+ for (const additional of additionalBuffers) {
13171
+ entries.push({
13172
+ binding: additional.binding,
13173
+ resource: { kind: "buffer", value: { buffer: additional.buffer } }
13174
+ });
13175
+ }
12252
13176
  const res = device.createBindGroup({
12253
13177
  label: "fullscreen-post-process-bg",
12254
13178
  layout: bgl,
@@ -12540,7 +13464,13 @@ function dispatchFullscreenPass(ctx, name, shader, color, reads, resolveCtx, com
12540
13464
  detail: { readsKey: reads[0] ?? "ldrColor", passName: name }
12541
13465
  });
12542
13466
  }
12543
- recordFxaaPass(requireRenderGraphRecordContext(ctx), resolveCtx, graphPass, paramsOverride);
13467
+ recordFxaaPass(
13468
+ requireRenderGraphRecordContext(ctx),
13469
+ resolveCtx,
13470
+ graphPass,
13471
+ paramsOverride,
13472
+ graphOutputFormat
13473
+ );
12544
13474
  return;
12545
13475
  }
12546
13476
  const lookup = ctx.runtime.lookupPostProcess;
@@ -12733,6 +13663,11 @@ var TEMPORAL_HISTORY_FORMATS = Object.freeze({
12733
13663
  temporal: "rgba16float",
12734
13664
  stability: "r8unorm"
12735
13665
  });
13666
+ var CLOUD_HISTORY_FORMATS = Object.freeze({
13667
+ radiance: "rgba16float",
13668
+ transmittance: "rgba16float",
13669
+ depth: "rgba16float"
13670
+ });
12736
13671
  function createSurface(device, childScope, label, width, height, format = TEMPORAL_HISTORY_FORMATS.color) {
12737
13672
  const texture = device.createTexture({
12738
13673
  label,
@@ -12756,8 +13691,15 @@ function createSurface(device, childScope, label, width, height, format = TEMPOR
12756
13691
  if (!view.ok) throw view.error;
12757
13692
  return { texture: texture.value, view: view.value };
12758
13693
  }
12759
- function createState(device, scope, width, height) {
13694
+ function cloudHistoryExtent(width, height) {
13695
+ return {
13696
+ width: Math.max(1, Math.ceil(width / 2)),
13697
+ height: Math.max(1, Math.ceil(height / 2))
13698
+ };
13699
+ }
13700
+ function createState(device, scope, width, height, cloudHistoryEnabled) {
12760
13701
  const childScope = scope.createChild(`${scope.owner}:temporal`);
13702
+ const cloudExtent = cloudHistoryExtent(width, height);
12761
13703
  try {
12762
13704
  return {
12763
13705
  device,
@@ -12808,6 +13750,59 @@ function createState(device, scope, width, height) {
12808
13750
  TEMPORAL_HISTORY_FORMATS.stability
12809
13751
  )
12810
13752
  ],
13753
+ cloudHistoryEnabled,
13754
+ cloudRadiance: cloudHistoryEnabled ? [
13755
+ createSurface(
13756
+ device,
13757
+ childScope,
13758
+ "cloud-history-radiance-a",
13759
+ cloudExtent.width,
13760
+ cloudExtent.height
13761
+ ),
13762
+ createSurface(
13763
+ device,
13764
+ childScope,
13765
+ "cloud-history-radiance-b",
13766
+ cloudExtent.width,
13767
+ cloudExtent.height
13768
+ )
13769
+ ] : void 0,
13770
+ cloudTransmittance: cloudHistoryEnabled ? [
13771
+ createSurface(
13772
+ device,
13773
+ childScope,
13774
+ "cloud-history-transmittance-a",
13775
+ cloudExtent.width,
13776
+ cloudExtent.height,
13777
+ CLOUD_HISTORY_FORMATS.transmittance
13778
+ ),
13779
+ createSurface(
13780
+ device,
13781
+ childScope,
13782
+ "cloud-history-transmittance-b",
13783
+ cloudExtent.width,
13784
+ cloudExtent.height,
13785
+ CLOUD_HISTORY_FORMATS.transmittance
13786
+ )
13787
+ ] : void 0,
13788
+ cloudDepth: cloudHistoryEnabled ? [
13789
+ createSurface(
13790
+ device,
13791
+ childScope,
13792
+ "cloud-history-depth-a",
13793
+ cloudExtent.width,
13794
+ cloudExtent.height,
13795
+ CLOUD_HISTORY_FORMATS.depth
13796
+ ),
13797
+ createSurface(
13798
+ device,
13799
+ childScope,
13800
+ "cloud-history-depth-b",
13801
+ cloudExtent.width,
13802
+ cloudExtent.height,
13803
+ CLOUD_HISTORY_FORMATS.depth
13804
+ )
13805
+ ] : void 0,
12811
13806
  bindGroupLayout: void 0,
12812
13807
  sampler: void 0,
12813
13808
  temporalSampler: void 0,
@@ -12842,16 +13837,17 @@ function getTemporalParamsBuffer(state) {
12842
13837
  state.paramsBuffer = created.value;
12843
13838
  return created.value;
12844
13839
  }
12845
- function getTemporalGpuState(frameState, device, scope, width, height) {
13840
+ function getTemporalGpuState(frameState, device, scope, width, height, cloudHistoryRequested = false) {
13841
+ const wantsCloudHistory = cloudHistoryRequested || frameState.pendingCloudHistoryActive === true || frameState.cloudHistoryActive === true;
13842
+ 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
13843
+ // the two shapes distinct so turning CloudLayer off retires its six HDR
13844
+ // surfaces instead of retaining them on an otherwise TAA-only frame.
13845
+ state.cloudHistoryEnabled === wantsCloudHistory;
12846
13846
  const staged = frameState.temporalGpuState;
12847
- if (staged !== void 0 && staged.scope === scope && staged.width === width && staged.height === height) {
12848
- return staged;
12849
- }
13847
+ if (matches(staged)) return staged;
12850
13848
  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);
13849
+ if (matches(existing)) return existing;
13850
+ const next = createState(device, scope, width, height, wantsCloudHistory);
12855
13851
  frameState.temporalGpuState = next;
12856
13852
  return next;
12857
13853
  }
@@ -13135,7 +14131,11 @@ function addTypedScenePass(graph, options) {
13135
14131
  resource: target.view,
13136
14132
  usage: "sampled-read"
13137
14133
  })),
14134
+ ...options.cloudShadow === void 0 ? [] : [{ resource: options.cloudShadow.view, usage: "sampled-read" }],
13138
14135
  ...options.transmissionBackdrop === void 0 ? [] : [{ resource: options.transmissionBackdrop, usage: "sampled-read" }],
14136
+ ...options.surfacePair?.rawDepth.status === "available" ? [{ resource: options.surfacePair.rawDepth.view, usage: "sampled-read" }] : [],
14137
+ ...options.recordMode === "single-layer-medium-color" && options.surfaceNearestLayer !== void 0 ? [{ resource: options.surfaceNearestLayer, usage: "sampled-read" }] : [],
14138
+ ...options.recordMode === "single-layer-medium-color" && options.surfaceNearestDepth !== void 0 ? [{ resource: options.surfaceNearestDepth, usage: "sampled-read" }] : [],
13139
14139
  ...options.environment === void 0 ? [] : [options.environment.irradiance, options.environment.prefilter].map((resource) => ({
13140
14140
  resource,
13141
14141
  usage: "sampled-read"
@@ -13177,8 +14177,12 @@ function addTypedScenePass(graph, options) {
13177
14177
  const internal = frame;
13178
14178
  const directionalShadow = options.directionalShadow === void 0 ? void 0 : resolvedView(resources, options.directionalShadow.view);
13179
14179
  const spotShadow = options.spotShadow === void 0 ? void 0 : resolvedView(resources, options.spotShadow.view);
14180
+ const cloudShadow = options.cloudShadow === void 0 ? void 0 : resolvedView(resources, options.cloudShadow.view);
13180
14181
  const ssao = options.ssao === void 0 ? void 0 : resolvedView(resources, options.ssao.view);
13181
14182
  const transmissionBackdrop = options.transmissionBackdrop === void 0 ? null : resolvedView(resources, options.transmissionBackdrop);
14183
+ const surfaceRawDepth = options.surfacePair?.rawDepth.status === "available" ? resolvedView(resources, options.surfacePair.rawDepth.view) : null;
14184
+ const surfaceNearestLayer = options.surfaceNearestLayer === void 0 ? null : resolvedView(resources, options.surfaceNearestLayer);
14185
+ const surfaceNearestDepth = options.surfaceNearestDepth === void 0 ? null : resolvedView(resources, options.surfaceNearestDepth);
13182
14186
  internal.frameState.currentDirectionalShadowView = directionalShadow ?? null;
13183
14187
  internal.frameState.currentSpotShadowView = spotShadow ?? null;
13184
14188
  const groups = buildPerFrameBindGroups(
@@ -13190,6 +14194,7 @@ function addTypedScenePass(graph, options) {
13190
14194
  {
13191
14195
  directionalShadow,
13192
14196
  spotShadow,
14197
+ cloudShadow,
13193
14198
  projector: internal.spotLightProjector?.view ?? internal.volumetricFog?.projectorView,
13194
14199
  projectorSampler: internal.spotLightProjector?.sampler ?? internal.volumetricFog?.projectorSampler
13195
14200
  },
@@ -13225,11 +14230,17 @@ function addTypedScenePass(graph, options) {
13225
14230
  passKind: options.passKind ?? "forward",
13226
14231
  ...options.clearColor === void 0 ? {} : { clearColor: options.clearColor },
13227
14232
  ...options.recordMode === void 0 ? {} : { recordMode: options.recordMode },
14233
+ ...options.transparentDepthWrite === void 0 ? {} : { transparentDepthWrite: options.transparentDepthWrite },
13228
14234
  ...options.coverageOnly === void 0 ? {} : { coverageOnly: options.coverageOnly },
13229
14235
  ...options.excludeSelector === void 0 ? {} : { excludeSelector: options.excludeSelector },
13230
14236
  ...options.includeSelector === void 0 ? {} : { includeSelector: options.includeSelector },
13231
14237
  ...options.transmissionBackdrop === void 0 ? {} : { transmissionBackdropView: transmissionBackdrop },
13232
- ...options.gpuDriven === void 0 ? {} : { gpuDriven: { projection: options.gpuDriven, resources } }
14238
+ ...surfaceRawDepth === null ? {} : { surfaceRawDepthView: surfaceRawDepth },
14239
+ ...surfaceNearestLayer === null ? {} : { surfaceNearestLayerView: surfaceNearestLayer },
14240
+ ...surfaceNearestDepth === null ? {} : { surfaceNearestDepthView: surfaceNearestDepth },
14241
+ ...options.recordMode === "single-layer-medium-nearest-layer" ? { fragmentEntryPoint: "fs_nearest_layer" } : options.recordMode === "single-layer-medium-color" ? { fragmentEntryPoint: "fs_color" } : {},
14242
+ ...options.gpuDriven === void 0 ? {} : { gpuDriven: { projection: options.gpuDriven, resources } },
14243
+ ...options.gpuDrivenFilter === void 0 ? {} : { gpuDrivenFilter: options.gpuDrivenFilter }
13233
14244
  });
13234
14245
  if (passContext.materialUboPayloadCache !== void 0) {
13235
14246
  internal.materialUboPayloadCache = passContext.materialUboPayloadCache;
@@ -13772,6 +14783,11 @@ function addStandardSceneDataPass(graph, target, depth) {
13772
14783
  color: target,
13773
14784
  depth,
13774
14785
  selector: { LightMode: ["Deferred", "Forward"] },
14786
+ // The temporal producer runs before the Surface raw-depth/nearest-layer
14787
+ // pair. Keep it on the ordinary opaque Standard lane rather than asking
14788
+ // a medium material to assemble a bind group from resources that this
14789
+ // pass cannot own yet.
14790
+ recordMode: "opaque",
13775
14791
  passKind: "temporal",
13776
14792
  // The temporal producer re-rasterizes the current scene after the main
13777
14793
  // color pass has populated depth. Its output is a semantic motion target;
@@ -13797,6 +14813,6 @@ function addTaaResolvePass(graph, current, currentTemporal, previousColor, previ
13797
14813
  });
13798
14814
  }
13799
14815
 
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
14816
+ 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, 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, 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, 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, retireTemporalGpuState, retireTemporalGpuStateAfterFence, runIblPrecompute, selectGpuDrivenSceneIndexVariant, selectGpuLodLane, selectHdrpPbrPrewarmVariants, selectLazyEquirectHandle, selectLod, selectProbePrewarmVariants, selectSkinPrewarmVariants, selectStandardPbrTransmissionPrewarmVariants, 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 };
14817
+ //# sourceMappingURL=chunk-LNIUIKQ7.mjs.map
14818
+ //# sourceMappingURL=chunk-LNIUIKQ7.mjs.map