@forgeax/engine-render 0.1.28 → 0.1.30

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 (768) hide show
  1. package/README.md +856 -126
  2. package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
  3. package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
  4. package/dist/assembly/device-feature-admission.d.ts +4 -3
  5. package/dist/assembly/device-feature-admission.d.ts.map +1 -1
  6. package/dist/assembly/dynamic-geometry-host.d.ts +27 -0
  7. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  8. package/dist/assembly/dynamic-geometry-runtime.d.ts +20 -0
  9. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -0
  10. package/dist/assembly/factory.d.ts +3 -1
  11. package/dist/assembly/factory.d.ts.map +1 -1
  12. package/dist/assembly/gpu-driven-owner.d.ts +10 -0
  13. package/dist/assembly/gpu-driven-owner.d.ts.map +1 -0
  14. package/dist/assembly/host-contract.d.ts +14 -0
  15. package/dist/assembly/host-contract.d.ts.map +1 -1
  16. package/dist/assembly/material/assembly.d.ts +31 -1
  17. package/dist/assembly/material/assembly.d.ts.map +1 -1
  18. package/dist/assembly/material/pipeline-helpers.d.ts +24 -0
  19. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -0
  20. package/dist/assembly/material-shader-policy.d.ts +3 -1
  21. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  22. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  23. package/dist/assembly/recovery/failure-location.d.ts +12 -0
  24. package/dist/assembly/recovery/failure-location.d.ts.map +1 -0
  25. package/dist/assembly/recovery/recovery-attempt.d.ts +1 -6
  26. package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -1
  27. package/dist/assembly/recovery/renderer-recover.d.ts +7 -4
  28. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  29. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  30. package/dist/assembly/renderer-feature-inspection.d.ts +5 -0
  31. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -0
  32. package/dist/assembly/renderer-frame-transaction.d.ts +19 -0
  33. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  34. package/dist/assembly/renderer-helpers.d.ts +3 -0
  35. package/dist/assembly/renderer-helpers.d.ts.map +1 -1
  36. package/dist/assembly/renderer-inspection.d.ts +4 -0
  37. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  38. package/dist/assembly/shader-prewarm-policy.d.ts +7 -1
  39. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
  40. package/dist/assembly/skin-palette-owner.d.ts +8 -0
  41. package/dist/assembly/skin-palette-owner.d.ts.map +1 -0
  42. package/dist/assembly/ssr-shader-prewarm.d.ts +6 -0
  43. package/dist/assembly/ssr-shader-prewarm.d.ts.map +1 -0
  44. package/dist/assembly/webgpu-device-loss.d.ts +15 -0
  45. package/dist/assembly/webgpu-device-loss.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-pbr-ready.d.ts +38 -0
  47. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -0
  48. package/dist/assembly/webgpu-ready-mipmap.d.ts +11 -0
  49. package/dist/assembly/webgpu-ready-mipmap.d.ts.map +1 -0
  50. package/dist/assembly/webgpu-ready.d.ts +7 -3
  51. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  52. package/dist/assembly/webgpu-renderer-bootstrap.d.ts +10 -0
  53. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -0
  54. package/dist/assembly/webgpu-renderer-contract.d.ts +62 -0
  55. package/dist/assembly/webgpu-renderer-contract.d.ts.map +1 -0
  56. package/dist/assembly/webgpu-renderer-guards.d.ts +9 -0
  57. package/dist/assembly/webgpu-renderer-guards.d.ts.map +1 -0
  58. package/dist/assembly/webgpu-renderer-observation.d.ts +6 -0
  59. package/dist/assembly/webgpu-renderer-observation.d.ts.map +1 -0
  60. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts +12 -0
  61. package/dist/assembly/webgpu-renderer-recovery-failure.d.ts.map +1 -0
  62. package/dist/assembly/webgpu-renderer.d.ts +7 -141
  63. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  64. package/dist/assembly/webgpu-vertex-layouts.d.ts +28 -84
  65. package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
  66. package/dist/authoring.mjs +2 -2
  67. package/dist/capture/scene-projection.d.ts +41 -0
  68. package/dist/capture/scene-projection.d.ts.map +1 -0
  69. package/dist/{chunk-J52NMQKR.mjs → chunk-7MQ3XBSP.mjs} +1098 -844
  70. package/dist/chunk-7MQ3XBSP.mjs.map +1 -0
  71. package/dist/{chunk-GF523LHF.mjs → chunk-BLXGONR2.mjs} +30 -12
  72. package/dist/chunk-BLXGONR2.mjs.map +1 -0
  73. package/dist/{chunk-VSL23LZE.mjs → chunk-C3DDSXYK.mjs} +1188 -463
  74. package/dist/chunk-C3DDSXYK.mjs.map +1 -0
  75. package/dist/{chunk-IQMKJLNU.mjs → chunk-FUUO4UND.mjs} +443 -30
  76. package/dist/chunk-FUUO4UND.mjs.map +1 -0
  77. package/dist/{chunk-J6KACNOH.mjs → chunk-JRBDO2KB.mjs} +617 -7
  78. package/dist/chunk-JRBDO2KB.mjs.map +1 -0
  79. package/dist/{chunk-GE3SDD72.mjs → chunk-MDQJPY3T.mjs} +20 -40
  80. package/dist/chunk-MDQJPY3T.mjs.map +1 -0
  81. package/dist/{chunk-MYJ5RPJO.mjs → chunk-NO4WZCAH.mjs} +3 -3
  82. package/dist/chunk-NO4WZCAH.mjs.map +1 -0
  83. package/dist/{chunk-RBDBZ5R7.mjs → chunk-PA5DRJNI.mjs} +2 -2
  84. package/dist/chunk-PA5DRJNI.mjs.map +1 -0
  85. package/dist/{chunk-MBU4ZVE7.mjs → chunk-PSEQ6QPH.mjs} +4655 -892
  86. package/dist/chunk-PSEQ6QPH.mjs.map +1 -0
  87. package/dist/{chunk-JAASCMXA.mjs → chunk-S5UE2T5P.mjs} +289 -41
  88. package/dist/chunk-S5UE2T5P.mjs.map +1 -0
  89. package/dist/components/camera.d.ts +62 -2
  90. package/dist/components/camera.d.ts.map +1 -1
  91. package/dist/components/directional-light.d.ts +2 -2
  92. package/dist/components/dynamic-resolution.d.ts +15 -0
  93. package/dist/components/dynamic-resolution.d.ts.map +1 -0
  94. package/dist/components/index.d.ts +2 -0
  95. package/dist/components/index.d.ts.map +1 -1
  96. package/dist/components/instances.d.ts +6 -20
  97. package/dist/components/instances.d.ts.map +1 -1
  98. package/dist/components/light-helpers.d.ts.map +1 -1
  99. package/dist/components/reflection-probe.d.ts +1 -0
  100. package/dist/components/reflection-probe.d.ts.map +1 -1
  101. package/dist/components/scene-instance.d.ts +2 -1
  102. package/dist/components/scene-instance.d.ts.map +1 -1
  103. package/dist/components/screen-space-reflection.d.ts +14 -0
  104. package/dist/components/screen-space-reflection.d.ts.map +1 -0
  105. package/dist/components/skylight.d.ts +4 -1
  106. package/dist/components/skylight.d.ts.map +1 -1
  107. package/dist/construct-renderer.mjs +14809 -7570
  108. package/dist/construct-renderer.mjs.map +1 -1
  109. package/dist/device/device-scope.d.ts +2 -0
  110. package/dist/device/device-scope.d.ts.map +1 -1
  111. package/dist/device/gpu-residency.d.ts +3 -14
  112. package/dist/device/gpu-residency.d.ts.map +1 -1
  113. package/dist/dynamic-geometry.d.ts.map +1 -1
  114. package/dist/environment/background.d.ts +7 -0
  115. package/dist/environment/background.d.ts.map +1 -0
  116. package/dist/environment/ibl.d.ts +11 -0
  117. package/dist/environment/ibl.d.ts.map +1 -0
  118. package/dist/environment/storage.d.ts +14 -0
  119. package/dist/environment/storage.d.ts.map +1 -0
  120. package/dist/errors/gpu-driven.d.ts +6 -3
  121. package/dist/errors/gpu-driven.d.ts.map +1 -1
  122. package/dist/errors/render.d.ts +41 -4
  123. package/dist/errors/render.d.ts.map +1 -1
  124. package/dist/extract/camera.d.ts.map +1 -1
  125. package/dist/extract/contracts.d.ts +7 -0
  126. package/dist/extract/contracts.d.ts.map +1 -1
  127. package/dist/extract/gpu-driven.d.ts +50 -3
  128. package/dist/extract/gpu-driven.d.ts.map +1 -1
  129. package/dist/features/host.d.ts +23 -1
  130. package/dist/features/host.d.ts.map +1 -1
  131. package/dist/features/noise-texture.d.ts +17 -0
  132. package/dist/features/noise-texture.d.ts.map +1 -0
  133. package/dist/features/plan.d.ts +83 -2
  134. package/dist/features/plan.d.ts.map +1 -1
  135. package/dist/features/prepared-gpu-work.d.ts +37 -4
  136. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  137. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  138. package/dist/features/prepared-graphics.d.ts +5 -0
  139. package/dist/features/prepared-graphics.d.ts.map +1 -1
  140. package/dist/features/render-graph-compute.d.ts +5 -3
  141. package/dist/features/render-graph-compute.d.ts.map +1 -1
  142. package/dist/features/render-graph-contribution.d.ts +11 -3
  143. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  144. package/dist/features/render-graph-raster.d.ts +19 -3
  145. package/dist/features/render-graph-raster.d.ts.map +1 -1
  146. package/dist/features/types.d.ts +11 -0
  147. package/dist/features/types.d.ts.map +1 -1
  148. package/dist/fullscreen-post-process-pass.d.ts +2 -0
  149. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  150. package/dist/gpu-driven/batch-topology.d.ts +34 -1
  151. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  152. package/dist/gpu-driven/material-artifacts.d.ts +24 -0
  153. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -0
  154. package/dist/gpu-driven/material-bindings.d.ts +7 -0
  155. package/dist/gpu-driven/material-bindings.d.ts.map +1 -0
  156. package/dist/gpu-driven/pbr-program.d.ts +10 -0
  157. package/dist/gpu-driven/pbr-program.d.ts.map +1 -0
  158. package/dist/gpu-driven/prepared-draw.d.ts +2 -0
  159. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  160. package/dist/gpu-driven/production-raster.d.ts +169 -27
  161. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  162. package/dist/gpu-driven/shadow-views.d.ts +126 -0
  163. package/dist/gpu-driven/shadow-views.d.ts.map +1 -0
  164. package/dist/gpu-driven/view-gpu.d.ts +18 -2
  165. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  166. package/dist/gpu-resource.d.ts +5 -2
  167. package/dist/gpu-resource.d.ts.map +1 -1
  168. package/dist/gpu-scene-schema.d.ts +2 -8
  169. package/dist/gpu-scene-schema.d.ts.map +1 -1
  170. package/dist/gpu-scene.d.ts +14 -0
  171. package/dist/gpu-scene.d.ts.map +1 -1
  172. package/dist/gpu-texture-usage.d.ts +1 -0
  173. package/dist/gpu-texture-usage.d.ts.map +1 -1
  174. package/dist/hdrp-buffers.d.ts +9 -0
  175. package/dist/hdrp-buffers.d.ts.map +1 -1
  176. package/dist/ibl/IblPipelineCache.d.ts +2 -0
  177. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  178. package/dist/ibl/frame-resources.d.ts +8 -0
  179. package/dist/ibl/frame-resources.d.ts.map +1 -0
  180. package/dist/ibl/skylight-bind-group.d.ts +3 -1
  181. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  182. package/dist/index.d.ts +87 -75
  183. package/dist/index.d.ts.map +1 -1
  184. package/dist/index.mjs +10 -8
  185. package/dist/index.mjs.map +1 -1
  186. package/dist/inspection-types.d.ts +180 -1
  187. package/dist/inspection-types.d.ts.map +1 -1
  188. package/dist/instances-derived-bounds.d.ts +11 -0
  189. package/dist/instances-derived-bounds.d.ts.map +1 -1
  190. package/dist/instances.d.ts +89 -44
  191. package/dist/instances.d.ts.map +1 -1
  192. package/dist/internal.d.ts +3 -0
  193. package/dist/internal.d.ts.map +1 -1
  194. package/dist/internal.mjs +117 -9
  195. package/dist/internal.mjs.map +1 -1
  196. package/dist/lifecycle.d.ts +2 -1
  197. package/dist/lifecycle.d.ts.map +1 -1
  198. package/dist/material-row.d.ts +15 -0
  199. package/dist/material-row.d.ts.map +1 -0
  200. package/dist/materials.d.ts +15 -0
  201. package/dist/materials.d.ts.map +1 -1
  202. package/dist/pbr-pipeline.d.ts +23 -5
  203. package/dist/pbr-pipeline.d.ts.map +1 -1
  204. package/dist/pipeline/render-extent.d.ts +51 -0
  205. package/dist/pipeline/render-extent.d.ts.map +1 -0
  206. package/dist/pipeline/standard-build-context.d.ts +7 -0
  207. package/dist/pipeline/standard-build-context.d.ts.map +1 -0
  208. package/dist/pipeline/standard-forward-lane.d.ts +3 -2
  209. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  210. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts +12 -0
  211. package/dist/pipeline/standard-output/auto-exposure/capability.d.ts.map +1 -0
  212. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts +70 -0
  213. package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts.map +1 -0
  214. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts +75 -0
  215. package/dist/pipeline/standard-output/auto-exposure/graph.d.ts.map +1 -0
  216. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts +111 -0
  217. package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts.map +1 -0
  218. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts +16 -0
  219. package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts.map +1 -0
  220. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts +14 -0
  221. package/dist/pipeline/standard-output/auto-exposure/preset.d.ts.map +1 -0
  222. package/dist/pipeline/standard-output/auto-exposure/state.d.ts +46 -0
  223. package/dist/pipeline/standard-output/auto-exposure/state.d.ts.map +1 -0
  224. package/dist/pipeline/standard-output/color-transform.d.ts +27 -0
  225. package/dist/pipeline/standard-output/color-transform.d.ts.map +1 -0
  226. package/dist/pipeline/standard-output/graph.d.ts +15 -0
  227. package/dist/pipeline/standard-output/graph.d.ts.map +1 -0
  228. package/dist/pipeline/standard-output/lut-admission.d.ts +29 -0
  229. package/dist/pipeline/standard-output/lut-admission.d.ts.map +1 -0
  230. package/dist/pipeline/standard-output/lut-gpu.d.ts +48 -0
  231. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -0
  232. package/dist/pipeline/standard-output/lut-state.d.ts +68 -0
  233. package/dist/pipeline/standard-output/lut-state.d.ts.map +1 -0
  234. package/dist/pipeline/standard-output/resources.d.ts +10 -0
  235. package/dist/pipeline/standard-output/resources.d.ts.map +1 -0
  236. package/dist/pipeline/standard-output/types.d.ts +39 -0
  237. package/dist/pipeline/standard-output/types.d.ts.map +1 -0
  238. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  239. package/dist/pipeline/standard-post.d.ts +2 -2
  240. package/dist/pipeline/standard-post.d.ts.map +1 -1
  241. package/dist/pipeline/standard-profile.d.ts +2 -1
  242. package/dist/pipeline/standard-profile.d.ts.map +1 -1
  243. package/dist/pipeline-builder.d.ts +5 -2
  244. package/dist/pipeline-builder.d.ts.map +1 -1
  245. package/dist/pipeline-spec-types.d.ts +4 -0
  246. package/dist/pipeline-spec-types.d.ts.map +1 -1
  247. package/dist/pipeline-spec.d.ts +1 -9
  248. package/dist/pipeline-spec.d.ts.map +1 -1
  249. package/dist/plugin.d.ts.map +1 -1
  250. package/dist/points-lines/standard-owner.d.ts +1 -1
  251. package/dist/points-lines/standard-owner.d.ts.map +1 -1
  252. package/dist/post-process-errors.d.ts +9 -2
  253. package/dist/post-process-errors.d.ts.map +1 -1
  254. package/dist/prepare/extended-lighting/resources.d.ts +3 -3
  255. package/dist/prepare/prepared-graphics-resolver.d.ts +6 -1
  256. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  257. package/dist/record/dynamic-geometry-consumption.d.ts +15 -0
  258. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -0
  259. package/dist/record/frame-lighting.d.ts +3 -3
  260. package/dist/record/frame-lighting.d.ts.map +1 -1
  261. package/dist/record/frame-snapshot.d.ts +109 -13
  262. package/dist/record/frame-snapshot.d.ts.map +1 -1
  263. package/dist/record/frame-targets.d.ts.map +1 -1
  264. package/dist/record/frame.d.ts +41 -5
  265. package/dist/record/frame.d.ts.map +1 -1
  266. package/dist/record/main-pass-geometry.d.ts +13 -9
  267. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  268. package/dist/record/main-pass-material.d.ts +43 -3
  269. package/dist/record/main-pass-material.d.ts.map +1 -1
  270. package/dist/record/main-pass-sprite-draws.d.ts +2 -10
  271. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  272. package/dist/record/main-pass.d.ts +14 -2
  273. package/dist/record/main-pass.d.ts.map +1 -1
  274. package/dist/record/mesh-ssbo.d.ts +15 -6
  275. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  276. package/dist/record/prepared-material-bindings.d.ts +19 -0
  277. package/dist/record/prepared-material-bindings.d.ts.map +1 -0
  278. package/dist/record/recovery-pipeline.d.ts +1 -0
  279. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  280. package/dist/record/render-context.d.ts +101 -22
  281. package/dist/record/render-context.d.ts.map +1 -1
  282. package/dist/record/shadow-pass.d.ts +62 -7
  283. package/dist/record/shadow-pass.d.ts.map +1 -1
  284. package/dist/record/skybox-post-pass.d.ts +1 -1
  285. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  286. package/dist/record/typed-frame-graph.d.ts +39 -8
  287. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  288. package/dist/record/view-ubo.d.ts +1 -0
  289. package/dist/record/view-ubo.d.ts.map +1 -1
  290. package/dist/recovery/render-system-candidate.d.ts +10 -2
  291. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  292. package/dist/recovery/render-system-roots.d.ts +11 -0
  293. package/dist/recovery/render-system-roots.d.ts.map +1 -0
  294. package/dist/recovery/types.d.ts +76 -0
  295. package/dist/recovery/types.d.ts.map +1 -0
  296. package/dist/reflection/background.d.ts +14 -0
  297. package/dist/reflection/background.d.ts.map +1 -0
  298. package/dist/reflection/filter.d.ts.map +1 -1
  299. package/dist/reflection/projection.d.ts +1 -0
  300. package/dist/reflection/projection.d.ts.map +1 -1
  301. package/dist/reflection/record-owner.d.ts +4 -4
  302. package/dist/reflection/record-owner.d.ts.map +1 -1
  303. package/dist/render-contract.d.ts +211 -53
  304. package/dist/render-contract.d.ts.map +1 -1
  305. package/dist/render-graph-primitives.d.ts +1 -0
  306. package/dist/render-graph-primitives.d.ts.map +1 -1
  307. package/dist/render-pipeline.d.ts +81 -6
  308. package/dist/render-pipeline.d.ts.map +1 -1
  309. package/dist/render-system-extract-tail.d.ts +15 -6
  310. package/dist/render-system-extract-tail.d.ts.map +1 -1
  311. package/dist/render-system-extract.d.ts +128 -41
  312. package/dist/render-system-extract.d.ts.map +1 -1
  313. package/dist/render-system-projections.d.ts +22 -0
  314. package/dist/render-system-projections.d.ts.map +1 -0
  315. package/dist/render-system.d.ts +27 -77
  316. package/dist/render-system.d.ts.map +1 -1
  317. package/dist/scene/render-scene-types.d.ts +14 -7
  318. package/dist/scene/render-scene-types.d.ts.map +1 -1
  319. package/dist/scene/render-scene.d.ts +31 -11
  320. package/dist/scene/render-scene.d.ts.map +1 -1
  321. package/dist/scene/shadow-visibility.d.ts +5 -0
  322. package/dist/scene/shadow-visibility.d.ts.map +1 -0
  323. package/dist/ssao-config.d.ts +8 -6
  324. package/dist/ssao-config.d.ts.map +1 -1
  325. package/dist/ssr/admission.d.ts +70 -1
  326. package/dist/ssr/admission.d.ts.map +1 -1
  327. package/dist/ssr/compose.d.ts +13 -0
  328. package/dist/ssr/compose.d.ts.map +1 -0
  329. package/dist/ssr/errors.d.ts +35 -0
  330. package/dist/ssr/errors.d.ts.map +1 -1
  331. package/dist/ssr/graph.d.ts +60 -0
  332. package/dist/ssr/graph.d.ts.map +1 -0
  333. package/dist/ssr/history.d.ts +97 -0
  334. package/dist/ssr/history.d.ts.map +1 -0
  335. package/dist/ssr/hiz.d.ts +37 -0
  336. package/dist/ssr/hiz.d.ts.map +1 -0
  337. package/dist/ssr/inspection.d.ts +42 -0
  338. package/dist/ssr/inspection.d.ts.map +1 -0
  339. package/dist/ssr/resources.d.ts +58 -0
  340. package/dist/ssr/resources.d.ts.map +1 -0
  341. package/dist/ssr/temporal.d.ts +38 -0
  342. package/dist/ssr/temporal.d.ts.map +1 -0
  343. package/dist/systems/skin-palette-allocator.d.ts +32 -10
  344. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  345. package/dist/systems/skin-palette-types.d.ts +15 -0
  346. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  347. package/dist/systems/transparent-dispatch.d.ts +9 -0
  348. package/dist/systems/transparent-dispatch.d.ts.map +1 -0
  349. package/dist/targets/material-source.d.ts +7 -0
  350. package/dist/targets/material-source.d.ts.map +1 -1
  351. package/dist/temporal/frame-coordinator.d.ts +7 -0
  352. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  353. package/dist/temporal/gpu.d.ts +8 -0
  354. package/dist/temporal/gpu.d.ts.map +1 -1
  355. package/dist/temporal/history.d.ts.map +1 -1
  356. package/dist/temporal/index.mjs +6 -6
  357. package/dist/temporal/inspection.d.ts.map +1 -1
  358. package/dist/temporal/standard-scene-data.d.ts +4 -2
  359. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  360. package/dist/temporal/target-coverage-attachment.d.ts +15 -0
  361. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -0
  362. package/dist/temporal/temporal-view.d.ts +6 -0
  363. package/dist/temporal/temporal-view.d.ts.map +1 -1
  364. package/dist/temporal/view.d.ts +6 -0
  365. package/dist/temporal/view.d.ts.map +1 -1
  366. package/dist/typed-render-graph-primitives.d.ts +41 -1
  367. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  368. package/dist/typed-shadow-passes.d.ts +3 -1
  369. package/dist/typed-shadow-passes.d.ts.map +1 -1
  370. package/dist/volume/component.d.ts +1 -0
  371. package/dist/volume/component.d.ts.map +1 -1
  372. package/dist/volume/temporal.d.ts +6 -0
  373. package/dist/volume/temporal.d.ts.map +1 -1
  374. package/package.json +21 -20
  375. package/src/__tests__/auto-exposure-gpu-evidence.ts +291 -0
  376. package/src/__tests__/auto-exposure-inspection.unit.test.ts +80 -0
  377. package/src/__tests__/auto-exposure-transaction.integration.test.ts +99 -0
  378. package/src/__tests__/auto-exposure.browser.test.ts +33 -0
  379. package/src/__tests__/auto-exposure.dawn.test.ts +33 -0
  380. package/src/__tests__/capture-scene-projection.unit.test.ts +24 -0
  381. package/src/__tests__/detached-inspection.integration.test.ts +5 -0
  382. package/src/__tests__/device-feature-admission.unit.test.ts +15 -24
  383. package/src/__tests__/device-loss-fanout.unit.test.ts +43 -0
  384. package/src/__tests__/device-scope-lifecycle.unit.test.ts +18 -0
  385. package/src/__tests__/device-scope-stale-matrix.unit.test.ts +18 -0
  386. package/src/__tests__/docs-gate-green.unit.test.ts +3 -3
  387. package/src/__tests__/dynamic-geometry-batch.unit.test.ts +157 -0
  388. package/src/__tests__/dynamic-geometry.unit.test.ts +36 -0
  389. package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +81 -0
  390. package/src/__tests__/factory-contract.integration.test.ts +231 -9
  391. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +19 -0
  392. package/src/__tests__/feature-depth-input.dawn.test.ts +121 -0
  393. package/src/__tests__/feature-noise.unit.test.ts +38 -0
  394. package/src/__tests__/fixtures/taa-resolve-pinned-baseline.wgsl +301 -0
  395. package/src/__tests__/frame-camera-selection.unit.test.ts +131 -0
  396. package/src/__tests__/frame-observation.contract.test.ts +21 -0
  397. package/src/__tests__/frame-plan-contract.unit.test.ts +24 -0
  398. package/src/__tests__/frame-targets.unit.test.ts +24 -0
  399. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +3 -0
  400. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +79 -0
  401. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +307 -7
  402. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +122 -142
  403. package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +10 -1
  404. package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +261 -0
  405. package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +346 -0
  406. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1422 -0
  407. package/src/__tests__/gpu-driven-pbr.integration.test.ts +21 -0
  408. package/src/__tests__/gpu-driven-production-fixture.ts +96 -0
  409. package/src/__tests__/gpu-driven-production.integration.test.ts +1076 -106
  410. package/src/__tests__/gpu-driven-scaling.unit.test.ts +1 -3
  411. package/src/__tests__/gpu-driven-shadow-views.browser.test.ts +63 -0
  412. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +294 -0
  413. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +97 -0
  414. package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +168 -0
  415. package/src/__tests__/gpu-driven-skin-contract.test-d.ts +11 -0
  416. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +72 -20
  417. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +30 -9
  418. package/src/__tests__/gpu-driven-view.unit.test.ts +160 -52
  419. package/src/__tests__/gpu-pass-timing-browser-runner.ts +15 -0
  420. package/src/__tests__/gpu-pass-timing.browser.test.ts +20 -2
  421. package/src/__tests__/gpu-resource-scope.unit.test.ts +71 -0
  422. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +42 -0
  423. package/src/__tests__/gpu-scene-render-graph-gpu.ts +19 -5
  424. package/src/__tests__/gpu-scene.dawn.test.ts +40 -13
  425. package/src/__tests__/gpu-scene.unit.test.ts +613 -33
  426. package/src/__tests__/instances-culling.integration.test.ts +36 -10
  427. package/src/__tests__/instances-derived-bounds.unit.test.ts +54 -0
  428. package/src/__tests__/instances-store.unit.test.ts +242 -39
  429. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +6 -0
  430. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +13 -16
  431. package/src/__tests__/lut-lkg-transaction.integration.test.ts +122 -0
  432. package/src/__tests__/material-contract-inventory.unit.test.ts +5 -6
  433. package/src/__tests__/material-dispatch-shader-id.unit.test.ts +51 -0
  434. package/src/__tests__/material-lane-selection.unit.test.ts +60 -0
  435. package/src/__tests__/material-numeric-upload.unit.test.ts +53 -0
  436. package/src/__tests__/material-texture-handles.unit.test.ts +18 -0
  437. package/src/__tests__/material-texture-source.unit.test.ts +87 -0
  438. package/src/__tests__/materials-authoring-validation.unit.test.ts +41 -0
  439. package/src/__tests__/materials-standard-contract.unit.test.ts +57 -3
  440. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
  441. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +8 -0
  442. package/src/__tests__/morph-neutral-admission.unit.test.ts +19 -0
  443. package/src/__tests__/normal-fallback.dawn.test.ts +122 -0
  444. package/src/__tests__/particle-material-input-layout.unit.test.ts +104 -0
  445. package/src/__tests__/physical-clearcoat.integration.test.ts +42 -3
  446. package/src/__tests__/pipeline-texture-specialization.unit.test.ts +138 -0
  447. package/src/__tests__/point-shadow-inspection.unit.test.ts +2 -0
  448. package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -5
  449. package/src/__tests__/prepared-gpu-driven-pbr-contract.test-d.ts +31 -0
  450. package/src/__tests__/prepared-gpu-driven-pbr-contract.unit.test.ts +39 -0
  451. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +251 -9
  452. package/src/__tests__/prepared-graphics-capability.unit.test.ts +21 -0
  453. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +6 -2
  454. package/src/__tests__/profiler-phase-catalog.test.ts +5 -0
  455. package/src/__tests__/public-surface.test-d.ts +3 -0
  456. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +30 -12
  457. package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +171 -0
  458. package/src/__tests__/reflection-probe-authoring.unit.test.ts +12 -10
  459. package/src/__tests__/reflection-probe-box.dawn.test.ts +71 -0
  460. package/src/__tests__/reflection-probe-filter.unit.test.ts +9 -0
  461. package/src/__tests__/reflection-probe-orientation.dawn.test.ts +294 -0
  462. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +5 -14
  463. package/src/__tests__/reflection-probe-updates.unit.test.ts +129 -0
  464. package/src/__tests__/render-error-code-owner.test-d.ts +7 -0
  465. package/src/__tests__/render-error-detail-ssot.test-d.ts +27 -1
  466. package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
  467. package/src/__tests__/render-extent.unit.test.ts +63 -0
  468. package/src/__tests__/render-feature-gpu-work.integration.test.ts +285 -2
  469. package/src/__tests__/render-feature-plan.unit.test.ts +245 -0
  470. package/src/__tests__/render-feature-shadow-order.unit.test.ts +228 -0
  471. package/src/__tests__/render-feature-zero-work.unit.test.ts +35 -1
  472. package/src/__tests__/render-graph-fallback.integration.test.ts +2 -2
  473. package/src/__tests__/render-owner-cohesion.unit.test.ts +55 -0
  474. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +426 -0
  475. package/src/__tests__/render-scene-projection.unit.test.ts +915 -23
  476. package/src/__tests__/render-scene-resource-updates.integration.test.ts +214 -0
  477. package/src/__tests__/render-scene-skin-lifecycle.integration.test.ts +173 -0
  478. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +133 -0
  479. package/src/__tests__/render-target-material-source.test-d.ts +27 -3
  480. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +233 -9
  481. package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
  482. package/src/__tests__/shader-manifest-fixture.ts +45 -0
  483. package/src/__tests__/skin-motion-regression.unit.test.ts +0 -33
  484. package/src/__tests__/skin-palette-persistent.integration.test.ts +28 -0
  485. package/src/__tests__/skin-palette-persistent.unit.test.ts +247 -0
  486. package/src/__tests__/skinned-shadow-caster.test.ts +125 -14
  487. package/src/__tests__/specular-environment-scale.dawn.test.ts +158 -0
  488. package/src/__tests__/ssao-config.unit.test.ts +7 -0
  489. package/src/__tests__/ssao-surface.dawn.test.ts +252 -0
  490. package/src/__tests__/ssr-admission-matrix.integration.test.ts +7 -1
  491. package/src/__tests__/ssr-confidence-compose.unit.test.ts +84 -0
  492. package/src/__tests__/ssr-coordinate-oracle.unit.test.ts +28 -0
  493. package/src/__tests__/ssr-cube-silhouette.dawn.test.ts +270 -0
  494. package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
  495. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +99 -0
  496. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +116 -0
  497. package/src/__tests__/ssr-gpu-dispatch.ts +951 -0
  498. package/src/__tests__/ssr-graph-topology.unit.test.ts +104 -0
  499. package/src/__tests__/ssr-history-filter.dawn.test.ts +198 -0
  500. package/src/__tests__/ssr-hit-color.dawn.test.ts +273 -0
  501. package/src/__tests__/ssr-hiz-odd-reduction.dawn.test.ts +569 -0
  502. package/src/__tests__/ssr-hiz-rescue.dawn.test.ts +279 -0
  503. package/src/__tests__/ssr-hiz.browser.test.ts +150 -0
  504. package/src/__tests__/ssr-hiz.dawn.test.ts +150 -0
  505. package/src/__tests__/ssr-hiz.unit.test.ts +56 -0
  506. package/src/__tests__/ssr-inspection.unit.test.ts +105 -0
  507. package/src/__tests__/ssr-memory-budget.unit.test.ts +45 -0
  508. package/src/__tests__/ssr-performance-sequence-aggregation.unit.test.ts +15 -0
  509. package/src/__tests__/ssr-public-surface.test-d.ts +37 -0
  510. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +387 -0
  511. package/src/__tests__/ssr-reflection-mip-reducer.dawn.test.ts +309 -0
  512. package/src/__tests__/ssr-reprojection-probe.ts +90 -0
  513. package/src/__tests__/ssr-roughness-mip.dawn.test.ts +163 -0
  514. package/src/__tests__/ssr-shader-prewarm.unit.test.ts +59 -0
  515. package/src/__tests__/ssr-spatial.integration.test.ts +141 -0
  516. package/src/__tests__/ssr-stable-lattice.dawn.test.ts +475 -0
  517. package/src/__tests__/ssr-temporal-history.unit.test.ts +202 -0
  518. package/src/__tests__/ssr-texel-crossing.dawn.test.ts +448 -0
  519. package/src/__tests__/ssr-zero-work.integration.test.ts +87 -0
  520. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +84 -12
  521. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +29 -0
  522. package/src/__tests__/standard-output-chain-contract.unit.test.ts +99 -0
  523. package/src/__tests__/standard-output-chain.integration.test.ts +73 -0
  524. package/src/__tests__/standard-output-gpu-evidence.ts +205 -0
  525. package/src/__tests__/standard-output.browser.test.ts +15 -0
  526. package/src/__tests__/standard-output.dawn.test.ts +15 -0
  527. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +275 -0
  528. package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
  529. package/src/__tests__/standard-profile-oracle.unit.test.ts +49 -0
  530. package/src/__tests__/standard-surface-lighting.unit.test.ts +41 -0
  531. package/src/__tests__/standard-texture-specialization.dawn.test.ts +141 -0
  532. package/src/__tests__/surface-adjacent-regressions.integration.test.ts +6 -3
  533. package/src/__tests__/taa-coverage-edge.dawn.test.ts +199 -0
  534. package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
  535. package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +782 -0
  536. package/src/__tests__/taa-stability-feedback.browser.test.ts +23 -0
  537. package/src/__tests__/taa-stability-feedback.dawn.test.ts +68 -0
  538. package/src/__tests__/taa-stability-feedback.ts +342 -0
  539. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +49 -7
  540. package/src/__tests__/temporal-reset-matrix.unit.test.ts +9 -0
  541. package/src/__tests__/temporal-transaction.integration.test.ts +28 -0
  542. package/src/__tests__/temporal-view.unit.test.ts +17 -0
  543. package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
  544. package/src/__tests__/transmission-prewarm.unit.test.ts +57 -0
  545. package/src/__tests__/typed-pipeline-topology.unit.test.ts +109 -4
  546. package/src/__tests__/typed-scene-pass-material-cache.integration.test.ts +126 -0
  547. package/src/__tests__/vertex-layouts-ssot.unit.test.ts +47 -0
  548. package/src/__tests__/visibility-extract.perf.test.ts +20 -8
  549. package/src/__tests__/visibility-instances.integration.test.ts +19 -7
  550. package/src/__tests__/visibility-producer-matrix.integration.test.ts +20 -9
  551. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +62 -13
  552. package/src/__tests__/volumetric-fog-topology.unit.test.ts +7 -7
  553. package/src/assembly/atmosphere-shader-prewarm.ts +39 -0
  554. package/src/assembly/device-feature-admission.ts +9 -4
  555. package/src/assembly/dynamic-geometry-host.ts +284 -163
  556. package/src/assembly/dynamic-geometry-runtime.ts +71 -0
  557. package/src/assembly/factory.ts +4 -0
  558. package/src/assembly/gpu-driven-owner.ts +29 -0
  559. package/src/assembly/host-contract.ts +19 -0
  560. package/src/assembly/material/assembly.ts +383 -1
  561. package/src/assembly/material/pipeline-helpers.ts +100 -0
  562. package/src/assembly/material-shader-policy.ts +110 -46
  563. package/src/assembly/recovery/device-loss-fanout.ts +5 -0
  564. package/src/assembly/recovery/failure-location.ts +62 -0
  565. package/src/assembly/recovery/recovery-attempt.ts +2 -29
  566. package/src/assembly/recovery/renderer-recover.ts +16 -17
  567. package/src/assembly/renderer-facade.ts +34 -1
  568. package/src/assembly/renderer-feature-inspection.ts +13 -0
  569. package/src/assembly/renderer-frame-transaction.ts +63 -0
  570. package/src/assembly/renderer-helpers.ts +26 -0
  571. package/src/assembly/renderer-inspection.ts +6 -0
  572. package/src/assembly/shader-prewarm-policy.ts +46 -1
  573. package/src/assembly/skin-palette-owner.ts +21 -0
  574. package/src/assembly/ssr-shader-prewarm.ts +41 -0
  575. package/src/assembly/webgpu-device-loss.ts +75 -0
  576. package/src/assembly/webgpu-pbr-ready.ts +232 -0
  577. package/src/assembly/webgpu-ready-mipmap.ts +26 -0
  578. package/src/assembly/webgpu-ready.ts +161 -131
  579. package/src/assembly/webgpu-renderer-bootstrap.ts +85 -0
  580. package/src/assembly/webgpu-renderer-contract.ts +69 -0
  581. package/src/assembly/webgpu-renderer-guards.ts +32 -0
  582. package/src/assembly/webgpu-renderer-observation.ts +43 -0
  583. package/src/assembly/webgpu-renderer-recovery-failure.ts +62 -0
  584. package/src/assembly/webgpu-renderer.ts +744 -730
  585. package/src/assembly/webgpu-vertex-layouts.ts +233 -87
  586. package/src/capture/scene-projection.ts +37 -0
  587. package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
  588. package/src/components/__tests__/dynamic-resolution-schema.unit.test.ts +65 -0
  589. package/src/components/__tests__/light-radius.integration.test.ts +59 -0
  590. package/src/components/camera.ts +287 -7
  591. package/src/components/directional-light.ts +3 -3
  592. package/src/components/dynamic-resolution.ts +67 -0
  593. package/src/components/index.ts +2 -0
  594. package/src/components/instances.ts +45 -18
  595. package/src/components/light-helpers.ts +6 -1
  596. package/src/components/reflection-probe.ts +1 -0
  597. package/src/components/scene-instance.ts +2 -1
  598. package/src/components/screen-space-reflection.ts +21 -0
  599. package/src/components/skylight.ts +4 -1
  600. package/src/components/sprite-animation.ts +2 -2
  601. package/src/components/sprite-instances.ts +1 -1
  602. package/src/device/device-scope.ts +13 -7
  603. package/src/device/gpu-residency.ts +45 -42
  604. package/src/dynamic-geometry.ts +13 -8
  605. package/src/environment/background.ts +281 -0
  606. package/src/environment/ibl.ts +211 -0
  607. package/src/environment/storage.ts +63 -0
  608. package/src/errors/gpu-driven.ts +49 -8
  609. package/src/errors/render.ts +91 -3
  610. package/src/extract/camera.ts +37 -1
  611. package/src/extract/contracts.ts +10 -0
  612. package/src/extract/gpu-driven.ts +240 -10
  613. package/src/features/host.ts +237 -19
  614. package/src/features/noise-texture.ts +91 -0
  615. package/src/features/plan.ts +553 -24
  616. package/src/features/prepared-gpu-work.ts +631 -49
  617. package/src/features/prepared-graphics-store.ts +31 -0
  618. package/src/features/prepared-graphics.ts +5 -0
  619. package/src/features/render-graph-compute.ts +41 -8
  620. package/src/features/render-graph-contribution.ts +141 -3
  621. package/src/features/render-graph-raster.ts +143 -30
  622. package/src/features/types.ts +11 -0
  623. package/src/fullscreen-post-process-pass.ts +3 -0
  624. package/src/gpu-driven/batch-topology.ts +452 -108
  625. package/src/gpu-driven/material-artifacts.ts +179 -0
  626. package/src/gpu-driven/material-bindings.ts +41 -0
  627. package/src/gpu-driven/pbr-program.ts +31 -0
  628. package/src/gpu-driven/prepared-draw.ts +42 -6
  629. package/src/gpu-driven/production-raster.ts +2806 -716
  630. package/src/gpu-driven/shadow-views.ts +539 -0
  631. package/src/gpu-driven/view-gpu.ts +188 -41
  632. package/src/gpu-resource.ts +21 -2
  633. package/src/gpu-scene-schema.ts +61 -11
  634. package/src/gpu-scene.ts +197 -99
  635. package/src/gpu-texture-usage.ts +1 -0
  636. package/src/hdrp-buffers.ts +141 -36
  637. package/src/ibl/IblPipelineCache.ts +5 -0
  638. package/src/ibl/frame-resources.ts +38 -0
  639. package/src/ibl/skylight-bind-group.ts +32 -21
  640. package/src/index.ts +194 -75
  641. package/src/inspection-types.ts +207 -1
  642. package/src/instances-derived-bounds.ts +258 -34
  643. package/src/instances.ts +459 -150
  644. package/src/internal.ts +22 -0
  645. package/src/lifecycle.ts +2 -0
  646. package/src/material-row.ts +194 -0
  647. package/src/materials.ts +44 -8
  648. package/src/pbr-pipeline.ts +172 -19
  649. package/src/pipeline/render-extent.ts +111 -0
  650. package/src/pipeline/standard-build-context.ts +7 -0
  651. package/src/pipeline/standard-forward-lane.ts +74 -29
  652. package/src/pipeline/standard-output/__tests__/lut-admission.unit.test.ts +103 -0
  653. package/src/pipeline/standard-output/auto-exposure/__tests__/capability.unit.test.ts +40 -0
  654. package/src/pipeline/standard-output/auto-exposure/__tests__/gpu.contract.unit.test.ts +125 -0
  655. package/src/pipeline/standard-output/auto-exposure/__tests__/graph.contract.unit.test.ts +94 -0
  656. package/src/pipeline/standard-output/auto-exposure/__tests__/oracle.test.ts +108 -0
  657. package/src/pipeline/standard-output/auto-exposure/__tests__/preset.test.ts +26 -0
  658. package/src/pipeline/standard-output/auto-exposure/capability.ts +38 -0
  659. package/src/pipeline/standard-output/auto-exposure/gpu.ts +567 -0
  660. package/src/pipeline/standard-output/auto-exposure/graph.ts +221 -0
  661. package/src/pipeline/standard-output/auto-exposure/inspection.ts +231 -0
  662. package/src/pipeline/standard-output/auto-exposure/oracle.ts +291 -0
  663. package/src/pipeline/standard-output/auto-exposure/preset.ts +28 -0
  664. package/src/pipeline/standard-output/auto-exposure/state.ts +156 -0
  665. package/src/pipeline/standard-output/color-transform.ts +124 -0
  666. package/src/pipeline/standard-output/graph.ts +139 -0
  667. package/src/pipeline/standard-output/lut-admission.ts +121 -0
  668. package/src/pipeline/standard-output/lut-gpu.ts +399 -0
  669. package/src/pipeline/standard-output/lut-state.ts +176 -0
  670. package/src/pipeline/standard-output/resources.ts +121 -0
  671. package/src/pipeline/standard-output/types.ts +58 -0
  672. package/src/pipeline/standard-pipeline.ts +232 -70
  673. package/src/pipeline/standard-post.ts +190 -27
  674. package/src/pipeline/standard-profile.ts +2 -1
  675. package/src/pipeline-builder.ts +28 -9
  676. package/src/pipeline-spec-types.ts +4 -0
  677. package/src/pipeline-spec.ts +37 -29
  678. package/src/plugin.ts +4 -0
  679. package/src/points-lines/standard-owner.ts +6 -14
  680. package/src/post-process-errors.ts +26 -18
  681. package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +2 -2
  682. package/src/prepare/extended-lighting/resources.ts +3 -3
  683. package/src/prepare/prepared-graphics-resolver.ts +9 -2
  684. package/src/record/__tests__/main-pass-geometry.unit.test.ts +68 -0
  685. package/src/record/__tests__/material-bg-cache.unit.test.ts +45 -0
  686. package/src/record/__tests__/material-slot-plan.unit.test.ts +57 -0
  687. package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
  688. package/src/record/__tests__/recovery-pipeline.unit.test.ts +20 -1
  689. package/src/record/__tests__/sprite-material-abi.unit.test.ts +41 -6
  690. package/src/record/__tests__/temporal-payload.unit.test.ts +2 -0
  691. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +45 -0
  692. package/src/record/__tests__/view-ubo-layout.unit.test.ts +5 -0
  693. package/src/record/dynamic-geometry-consumption.ts +59 -0
  694. package/src/record/frame-lighting.ts +15 -12
  695. package/src/record/frame-snapshot.ts +146 -34
  696. package/src/record/frame-targets.ts +9 -0
  697. package/src/record/frame.ts +838 -170
  698. package/src/record/main-pass-geometry.ts +209 -103
  699. package/src/record/main-pass-material.ts +157 -40
  700. package/src/record/main-pass-sprite-draws.ts +16 -107
  701. package/src/record/main-pass.ts +141 -12
  702. package/src/record/material-uniforms.ts +1 -1
  703. package/src/record/mesh-ssbo.ts +59 -15
  704. package/src/record/prepared-material-bindings.ts +238 -0
  705. package/src/record/recovery-pipeline.ts +69 -90
  706. package/src/record/render-context.ts +123 -24
  707. package/src/record/shadow-pass.ts +1389 -230
  708. package/src/record/skybox-post-pass.ts +14 -3
  709. package/src/record/typed-frame-graph.ts +1064 -47
  710. package/src/record/view-ubo.ts +12 -1
  711. package/src/recovery/render-system-candidate.ts +135 -68
  712. package/src/recovery/render-system-roots.ts +113 -0
  713. package/src/recovery/types.ts +77 -0
  714. package/src/reflection/background.ts +151 -0
  715. package/src/reflection/filter.ts +3 -0
  716. package/src/reflection/projection.ts +16 -6
  717. package/src/reflection/record-owner.ts +308 -140
  718. package/src/render-contract.ts +237 -49
  719. package/src/render-graph-primitives.ts +34 -5
  720. package/src/render-pipeline.ts +90 -2
  721. package/src/render-system-extract-tail.ts +431 -162
  722. package/src/render-system-extract.ts +478 -119
  723. package/src/render-system-projections.ts +241 -0
  724. package/src/render-system.ts +715 -828
  725. package/src/scene/render-scene-types.ts +13 -4
  726. package/src/scene/render-scene.ts +577 -355
  727. package/src/scene/shadow-visibility.ts +21 -0
  728. package/src/ssao-config.ts +25 -8
  729. package/src/ssr/admission.ts +380 -14
  730. package/src/ssr/compose.ts +144 -0
  731. package/src/ssr/errors.ts +48 -0
  732. package/src/ssr/graph.ts +797 -0
  733. package/src/ssr/history.ts +436 -0
  734. package/src/ssr/hiz.ts +124 -0
  735. package/src/ssr/inspection.ts +124 -0
  736. package/src/ssr/resources.ts +202 -0
  737. package/src/ssr/temporal.ts +164 -0
  738. package/src/systems/skin-palette-allocator.ts +495 -148
  739. package/src/systems/skin-palette-types.ts +17 -0
  740. package/src/systems/transparent-dispatch.ts +90 -0
  741. package/src/targets/material-source.ts +34 -0
  742. package/src/temporal/coverage.ts +1 -1
  743. package/src/temporal/frame-coordinator.ts +23 -2
  744. package/src/temporal/gpu.ts +79 -12
  745. package/src/temporal/history.ts +3 -1
  746. package/src/temporal/inspection.ts +2 -1
  747. package/src/temporal/standard-scene-data.ts +10 -2
  748. package/src/temporal/target-coverage-attachment.ts +72 -0
  749. package/src/temporal/temporal-view.ts +11 -2
  750. package/src/temporal/view.ts +12 -2
  751. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +219 -139
  752. package/src/typed-render-graph-primitives.ts +304 -74
  753. package/src/typed-shadow-passes.ts +122 -12
  754. package/src/volume/component.ts +1 -0
  755. package/src/volume/passes.ts +3 -3
  756. package/src/volume/temporal.ts +10 -0
  757. package/dist/chunk-GE3SDD72.mjs.map +0 -1
  758. package/dist/chunk-GF523LHF.mjs.map +0 -1
  759. package/dist/chunk-IQMKJLNU.mjs.map +0 -1
  760. package/dist/chunk-J52NMQKR.mjs.map +0 -1
  761. package/dist/chunk-J6KACNOH.mjs.map +0 -1
  762. package/dist/chunk-JAASCMXA.mjs.map +0 -1
  763. package/dist/chunk-MBU4ZVE7.mjs.map +0 -1
  764. package/dist/chunk-MYJ5RPJO.mjs.map +0 -1
  765. package/dist/chunk-RBDBZ5R7.mjs.map +0 -1
  766. package/dist/chunk-VSL23LZE.mjs.map +0 -1
  767. package/src/__tests__/instances-world-ownership.integration.test.ts +0 -62
  768. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +0 -36
@@ -1,20 +1,172 @@
1
1
  import { GlyphText } from './chunk-ILQ5MEZF.mjs';
2
- import { MeshRenderer, MeshFilter, DirectionalLight, validateDirectionalLightData, PointLight, computeInvRangeSquared, SpotLight, degToCos, RectAreaLight, validateRectAreaLightData, directionalShadowQualityFromF32, PointLightShadow, Skylight, LightProbe, validateLightProbeData, SkyboxBackground, Atmosphere, Instances, Layer, Points, Lines, SortKey, resolveMeshMaterialBindings, pointShapeFromU32, PostProcessParams, CubeCamera, cubeCameraUpdateIntentFromF32, ReflectionProbe, reflectionProbeUpdateIntentFromF32, tonemapToU32, resolveVisibility, Fog, VolumetricFog, resolveSelectedVolumetricLight, extractVolumetricFog, MotionBlur, Camera, bloomEnabledFromF32, antialiasFromF32, tonemapFromF32, cameraProjectionFromF32 } from './chunk-JAASCMXA.mjs';
3
- import { SpriteRegionOverride, SpriteInstances, selectActiveCameraIndex, getActiveCamera } from './chunk-RBDBZ5R7.mjs';
4
- import { PROBE_BLEND_RECORD_CAPACITY, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_COPY_DST, IES_SLICE_CAPACITY, COOKIE_SLICE_CAPACITY, isStandardPbrSkinMaterialShader, selectPasses, resolveRenderTargetMaterialSource, PROBE_BLEND_RECORD_BYTE_SIZE, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, COOKIE_SLICE_SIZE, isCanonicalStandardPbrMaterialShader, isStandardPbrMaterialShader } from './chunk-IQMKJLNU.mjs';
5
- import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, SHADOW_ATLAS_DEFAULT_LAYERS, SkinMaterialMismatchError, MaterialSkinAttrMissingError, ShadowInvalidConfigError, EnvironmentSourceConflictError, FogCardinalityError, AtmosphereInvalidParameterError } from './chunk-J6KACNOH.mjs';
6
- import { err, ok, RhiError } from '@forgeax/engine-rhi';
2
+ import { MeshRenderer, MeshFilter, DirectionalLight, validateDirectionalLightData, PointLight, computeInvRangeSquared, SpotLight, degToCos, RectAreaLight, validateRectAreaLightData, directionalShadowQualityFromF32, PointLightShadow, Skylight, LightProbe, validateLightProbeData, SkyboxBackground, Atmosphere, Instances, Layer, Points, Lines, SortKey, resolveMeshMaterialBindings, pointShapeFromU32, PostProcessParams, buildCubeCameraFaceViews, CubeCamera, cubeCameraUpdateIntentFromF32, ReflectionProbe, reflectionProbeUpdateIntentFromF32, tonemapToU32, resolveVisibility, Fog, VolumetricFog, resolveSelectedVolumetricLight, extractVolumetricFog, MotionBlur, DynamicResolution, ScreenSpaceReflection, Camera, CAMERA_EXPOSURE_MODE_MANUAL, cameraExposureFromColumns, antialiasFromF32, validateDynamicResolutionCamera, bloomEnabledFromF32, tonemapFromF32, cameraProjectionFromF32 } from './chunk-S5UE2T5P.mjs';
3
+ import { SpriteRegionOverride, SpriteInstances, selectActiveCameraIndex, getActiveCamera } from './chunk-PA5DRJNI.mjs';
4
+ import { PROBE_BLEND_RECORD_CAPACITY, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_COPY_DST, gpuDrivenShadowDrawKey, IES_SLICE_CAPACITY, COOKIE_SLICE_CAPACITY, isStandardPbrSkinMaterialShader, buildGpuDrivenDraws, worldEntityKey, gpuDrivenSourceDrawItemIndex, selectPasses, resolveRenderTargetMaterialSource, isCanonicalStandardPbrMaterialShader, PROBE_BLEND_RECORD_BYTE_SIZE, GPU_BUFFER_USAGE_UNIFORM, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, COOKIE_SLICE_SIZE, isStandardPbrMaterialShader } from './chunk-FUUO4UND.mjs';
5
+ import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, SHADOW_ATLAS_DEFAULT_LAYERS, SkinMaterialMismatchError, MaterialSkinAttrMissingError, InstanceCollectionError, ShadowInvalidConfigError, EnvironmentSourceConflictError, FogCardinalityError, GPU_TEXTURE_USAGE_COPY_SRC, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GPU_TEXTURE_USAGE_STORAGE_BINDING, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, AtmosphereInvalidParameterError } from './chunk-JRBDO2KB.mjs';
6
+ import { R_MIN, ok, err, TextError, toShared, handleSlot, AssetError, ASSET_ERROR_HINTS, materialValuesToLinearRuntime, derive, unpackSlot, materialGuidText } from '@forgeax/engine-types';
7
+ import { err as err$1, ok as ok$1, RhiError } from '@forgeax/engine-rhi';
7
8
  import { resolveAssetHandle, walkMaterialPassesOverSharedRefs, selectMaterialPassProgram, materialParametersToParamSchema as materialParametersToParamSchema$1 } from '@forgeax/engine-assets-runtime';
8
- import { SpawnLightInvalidBoundsError, routeWorldError, SpriteInstancesMutuallyExclusiveWithInstancesError, SpriteInstancesRequiresSpriteShaderError, SpriteInstancesCountMismatchError, InstanceTransformsStrideMismatchError, readRenderArrayView } from '@forgeax/engine-ecs/projection';
9
+ import { SpawnLightInvalidBoundsError, routeWorldError, SpriteInstancesMutuallyExclusiveWithInstancesError, SpriteInstancesRequiresSpriteShaderError, SpriteInstancesCountMismatchError, readRenderArrayView } from '@forgeax/engine-ecs/projection';
9
10
  import { vec3, mat4, frustum, box3 } from '@forgeax/engine-math';
10
11
  import { AssetGuid } from '@forgeax/engine-pack/guid';
11
12
  import { Transform, GlobalTransform, MorphWeights } from '@forgeax/engine-scene';
12
- import { STANDARD_PIPELINE_PARAM_SCHEMA, DEFAULT_STANDARD_SURFACE_MODULE } from '@forgeax/engine-shader';
13
- import { R_MIN, err as err$1, ok as ok$1, TextError, toShared, handleSlot, AssetError, ASSET_ERROR_HINTS, materialValuesToLinearRuntime, derive, unpackSlot, materialGuidText } from '@forgeax/engine-types';
14
- import { PROCEDURAL_FLOATS_PER_VERTEX, deriveVertexLayoutProjection } from '@forgeax/engine-geometry';
13
+ import { standardTextureMask, DEFAULT_STANDARD_PBR_PARAM_SCHEMA, STANDARD_PIPELINE_PARAM_SCHEMA, DEFAULT_STANDARD_SURFACE_MODULE } from '@forgeax/engine-shader';
15
14
  import { Skin, SkinInstancesCoexistForbiddenError, SkeletonResolveFailedError, JointCountMismatchError, JointEntityDanglingError } from '@forgeax/engine-skinning';
15
+ import { PROCEDURAL_FLOATS_PER_VERTEX } from '@forgeax/engine-geometry';
16
16
  import { resetFontConcurrency, trackFontConcurrency, layoutGlyphText, conservativeCubeAabb, bakeGlyphMesh } from '@forgeax/engine-graphics-extras';
17
17
 
18
+ // src/ssr/hiz.ts
19
+ var SSR_HIZ_FORMAT = "r32float";
20
+ function validExtent(extent) {
21
+ return Number.isInteger(extent.width) && Number.isInteger(extent.height) && extent.width > 0 && extent.height > 0;
22
+ }
23
+ function requireExtent(extent) {
24
+ if (!validExtent(extent)) {
25
+ throw new RangeError("SSR Hi-Z extent must contain positive integer width and height");
26
+ }
27
+ }
28
+ function nextSsrHiZMipExtent(extent) {
29
+ requireExtent(extent);
30
+ return {
31
+ width: Math.max(1, Math.floor(extent.width / 2)),
32
+ height: Math.max(1, Math.floor(extent.height / 2))
33
+ };
34
+ }
35
+ function buildSsrHiZPlan(extent) {
36
+ requireExtent(extent);
37
+ const levels = [];
38
+ let current = { width: extent.width, height: extent.height };
39
+ let level = 0;
40
+ while (true) {
41
+ levels.push({ level, ...current });
42
+ if (current.width === 1 && current.height === 1) break;
43
+ current = nextSsrHiZMipExtent(current);
44
+ level += 1;
45
+ }
46
+ return Object.freeze({
47
+ extent: Object.freeze({ width: extent.width, height: extent.height }),
48
+ format: SSR_HIZ_FORMAT,
49
+ mipLevelCount: levels.length,
50
+ levels: Object.freeze(levels.map((entry) => Object.freeze(entry))),
51
+ graphSize: Object.freeze({ width: extent.width, height: extent.height })
52
+ });
53
+ }
54
+
55
+ // src/ssr/resources.ts
56
+ var SSR_TRACE_FORMAT = "rgba16float";
57
+ var SSR_R32FLOAT_BYTES_PER_PIXEL = 4;
58
+ var SSR_RGBA16FLOAT_BYTES_PER_PIXEL = 8;
59
+ var SSR_TEMPORAL_PARAMS_BYTES = 32;
60
+ var SSR_SPATIAL_MEMORY_BUDGET_BYTES = 45088768;
61
+ function halfExtent(extent) {
62
+ return {
63
+ width: Math.max(1, Math.floor(extent.width / 2)),
64
+ height: Math.max(1, Math.floor(extent.height / 2))
65
+ };
66
+ }
67
+ function byteCount(width, height, bytesPerPixel) {
68
+ const bytes = width * height * bytesPerPixel;
69
+ if (!Number.isSafeInteger(bytes)) {
70
+ throw new RangeError("SSR spatial descriptor byte count exceeds safe integer range");
71
+ }
72
+ return bytes;
73
+ }
74
+ function estimateSsrSpatialMemory(extent, options = {}) {
75
+ const half = halfExtent(extent);
76
+ const plan = buildSsrHiZPlan(half);
77
+ const temporal = options.temporal !== false;
78
+ const hizBytes = plan.levels.reduce(
79
+ (sum, level) => sum + byteCount(level.width, level.height, SSR_R32FLOAT_BYTES_PER_PIXEL),
80
+ 0
81
+ );
82
+ const traceBytes = byteCount(half.width, half.height, SSR_RGBA16FLOAT_BYTES_PER_PIXEL);
83
+ const hitReactivityBytes = byteCount(half.width, half.height, SSR_R32FLOAT_BYTES_PER_PIXEL);
84
+ const resolvedBytes = temporal ? plan.levels.reduce(
85
+ (sum, level) => sum + byteCount(level.width, level.height, SSR_RGBA16FLOAT_BYTES_PER_PIXEL),
86
+ 0
87
+ ) : 0;
88
+ const historyBytes = temporal ? half.width * half.height * 12 * 2 : 0;
89
+ const temporalParamsBytes = temporal ? SSR_TEMPORAL_PARAMS_BYTES : 0;
90
+ const fallbackInputBytes = byteCount(
91
+ extent.width,
92
+ extent.height,
93
+ SSR_RGBA16FLOAT_BYTES_PER_PIXEL
94
+ );
95
+ const ssrOwnedBytes = hizBytes + traceBytes + hitReactivityBytes + resolvedBytes + historyBytes + temporalParamsBytes + fallbackInputBytes;
96
+ return Object.freeze({
97
+ width: extent.width,
98
+ height: extent.height,
99
+ halfWidth: half.width,
100
+ halfHeight: half.height,
101
+ hizBytes,
102
+ traceBytes,
103
+ hitReactivityBytes,
104
+ resolvedBytes,
105
+ historyBytes,
106
+ temporalParamsBytes,
107
+ fallbackInputBytes,
108
+ ssrOwnedBytes,
109
+ budgetBytes: SSR_SPATIAL_MEMORY_BUDGET_BYTES,
110
+ withinBudget: ssrOwnedBytes <= SSR_SPATIAL_MEMORY_BUDGET_BYTES
111
+ });
112
+ }
113
+ function texture(graph, label, format, extent) {
114
+ const created = graph.createTexture(label, {
115
+ format,
116
+ size: { width: extent.width, height: extent.height },
117
+ domain: "linear-hdr"
118
+ });
119
+ if (!created.ok) return created;
120
+ const view = graph.view(created.value, { label: `${label}.view`, dimension: "2d" });
121
+ if (!view.ok) return view;
122
+ return ok({
123
+ texture: created.value,
124
+ view: view.value,
125
+ width: extent.width,
126
+ height: extent.height,
127
+ format
128
+ });
129
+ }
130
+ function createSsrHiZResources(graph, extent) {
131
+ const plan = buildSsrHiZPlan(halfExtent(extent));
132
+ const created = graph.createTexture("ssr-hiz", {
133
+ format: SSR_HIZ_FORMAT,
134
+ size: plan.graphSize,
135
+ mipLevelCount: plan.mipLevelCount
136
+ });
137
+ if (!created.ok) return created;
138
+ const levels = [];
139
+ for (const entry of plan.levels) {
140
+ const view = graph.view(created.value, {
141
+ label: `ssr-hiz.mip-${entry.level}.view`,
142
+ dimension: "2d",
143
+ baseMipLevel: entry.level,
144
+ mipLevelCount: 1
145
+ });
146
+ if (!view.ok) return view;
147
+ levels.push(view.value);
148
+ }
149
+ return ok({ plan, texture: created.value, levels: Object.freeze(levels) });
150
+ }
151
+ function createSsrSpatialResources(graph, extent) {
152
+ const hiz = createSsrHiZResources(graph, extent);
153
+ if (!hiz.ok) return hiz;
154
+ const traceExtent = halfExtent(extent);
155
+ const trace = texture(graph, "ssr-trace", SSR_TRACE_FORMAT, traceExtent);
156
+ if (!trace.ok) return trace;
157
+ const hitTexture = graph.createTexture("ssr-hit-reactivity", {
158
+ format: "r32float",
159
+ size: traceExtent
160
+ });
161
+ if (!hitTexture.ok) return hitTexture;
162
+ const hitReactivity = graph.view(hitTexture.value, {
163
+ label: "ssr-hit-reactivity.view",
164
+ dimension: "2d"
165
+ });
166
+ if (!hitReactivity.ok) return hitReactivity;
167
+ return ok({ hiz: hiz.value, trace: trace.value, hitReactivity: hitReactivity.value });
168
+ }
169
+
18
170
  // src/inspection-types.ts
19
171
  function projectLightInspection(input) {
20
172
  return Object.freeze({
@@ -87,6 +239,293 @@ function projectExtendedLightingInspection(state) {
87
239
  uploadBytes: state.descriptorBytes
88
240
  });
89
241
  }
242
+ var SSR_HISTORY_FORMAT = "rgba16float";
243
+ var HISTORY_USAGE = GPU_TEXTURE_USAGE_COPY_SRC | GPU_TEXTURE_USAGE_COPY_DST | GPU_TEXTURE_USAGE_TEXTURE_BINDING | GPU_TEXTURE_USAGE_STORAGE_BINDING | GPU_TEXTURE_USAGE_RENDER_ATTACHMENT;
244
+ function positiveDimension(value, field) {
245
+ if (!Number.isSafeInteger(value) || value <= 0) {
246
+ throw new RangeError(`${field} must be a positive safe integer.`);
247
+ }
248
+ return value;
249
+ }
250
+ function createResources(device, scope, width, height) {
251
+ const halfWidth = Math.max(1, Math.floor(width / 2));
252
+ const halfHeight = Math.max(1, Math.floor(height / 2));
253
+ const descriptor = {
254
+ label: "ssr-history-rgba16float",
255
+ size: { width: halfWidth, height: halfHeight, depthOrArrayLayers: 1 },
256
+ format: SSR_HISTORY_FORMAT,
257
+ usage: HISTORY_USAGE,
258
+ mipLevelCount: 1,
259
+ sampleCount: 1,
260
+ dimension: "2d",
261
+ viewFormats: void 0,
262
+ textureBindingViewDimension: void 0
263
+ };
264
+ const childScope = scope.createChild(`${scope.owner}:ssr-history`);
265
+ const slots = [];
266
+ for (const index of [0, 1]) {
267
+ const texture2 = device.createTexture({
268
+ ...descriptor,
269
+ label: `ssr-history-rgba16float-${index}`
270
+ });
271
+ if (!texture2.ok) {
272
+ childScope.abandon();
273
+ return texture2;
274
+ }
275
+ childScope._adopt("texture", texture2.value, (value) => {
276
+ device.destroyTexture(value);
277
+ });
278
+ const view = device.createTextureView(texture2.value, {
279
+ label: `ssr-history-rgba16float-${index}.view`,
280
+ dimension: "2d",
281
+ baseMipLevel: 0,
282
+ mipLevelCount: 1,
283
+ baseArrayLayer: 0,
284
+ arrayLayerCount: 1
285
+ });
286
+ if (!view.ok) {
287
+ childScope.abandon();
288
+ return view;
289
+ }
290
+ const surfaceTexture = device.createTexture({
291
+ ...descriptor,
292
+ label: `ssr-history-surface-${index}`,
293
+ format: "rgba8unorm"
294
+ });
295
+ if (!surfaceTexture.ok) {
296
+ childScope.abandon();
297
+ return surfaceTexture;
298
+ }
299
+ childScope._adopt("texture", surfaceTexture.value, (value) => {
300
+ device.destroyTexture(value);
301
+ });
302
+ const surfaceView = device.createTextureView(surfaceTexture.value, { dimension: "2d" });
303
+ if (!surfaceView.ok) {
304
+ childScope.abandon();
305
+ return surfaceView;
306
+ }
307
+ slots.push({
308
+ texture: texture2.value,
309
+ view: view.value,
310
+ surfaceTexture: surfaceTexture.value,
311
+ surfaceView: surfaceView.value
312
+ });
313
+ }
314
+ const params = device.createBuffer({
315
+ label: "ssr-temporal-params",
316
+ size: 32,
317
+ usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
318
+ mappedAtCreation: false
319
+ });
320
+ if (!params.ok) {
321
+ childScope.abandon();
322
+ return params;
323
+ }
324
+ childScope._adopt("buffer", params.value, (value) => {
325
+ device.destroyBuffer(value);
326
+ });
327
+ const cleared = device.queue.writeBuffer(params.value, 0, new Uint8Array(32));
328
+ if (!cleared.ok) {
329
+ childScope.abandon();
330
+ return cleared;
331
+ }
332
+ return ok({
333
+ width,
334
+ height,
335
+ halfWidth,
336
+ halfHeight,
337
+ bytes: halfWidth * halfHeight * 12 * 2,
338
+ descriptor,
339
+ slots,
340
+ paramsBuffer: params.value,
341
+ childScope
342
+ });
343
+ }
344
+ function failure(code, expected, hint, detail) {
345
+ return { code, expected, hint, ...{} };
346
+ }
347
+ var SsrHistoryOwner = class _SsrHistoryOwner {
348
+ constructor(device, scope, resources) {
349
+ this.device = device;
350
+ this.scope = scope;
351
+ this.activeResources = resources;
352
+ }
353
+ device;
354
+ scope;
355
+ activeResources;
356
+ retiringResources = /* @__PURE__ */ new Set();
357
+ retirementFencePending = false;
358
+ activeCandidate;
359
+ readIndex = 0;
360
+ valid = false;
361
+ state = "first-frame";
362
+ resetReason = "first-enable";
363
+ lastFailure;
364
+ resetCount = 0;
365
+ static create(input) {
366
+ const width = positiveDimension(input.width, "width");
367
+ const height = positiveDimension(input.height, "height");
368
+ const resources = createResources(input.device, input.scope, width, height);
369
+ return resources.ok ? ok(new _SsrHistoryOwner(input.device, input.scope, resources.value)) : resources;
370
+ }
371
+ get resources() {
372
+ if (this.activeResources === void 0) throw new Error("SSR history resources are retired.");
373
+ return this.activeResources;
374
+ }
375
+ beginFrame() {
376
+ if (this.activeResources === void 0 || this.state === "retired" || this.state === "disposed") {
377
+ return err(
378
+ failure(
379
+ "ssr-history-retired",
380
+ "SSR history resources are active",
381
+ "recreate the renderer-owned SSR history after device recovery"
382
+ )
383
+ );
384
+ }
385
+ if (this.activeCandidate !== void 0) {
386
+ return err(
387
+ failure(
388
+ "ssr-history-active",
389
+ "one SSR history candidate is active",
390
+ "commit or abort the active SSR history candidate before beginning another"
391
+ )
392
+ );
393
+ }
394
+ const writeSlot = this.valid ? this.readIndex === 0 ? 1 : 0 : 0;
395
+ const candidate = Object.freeze({
396
+ readSlot: this.valid ? this.readIndex : null,
397
+ writeSlot,
398
+ historyValid: this.valid && this.resetReason === void 0
399
+ });
400
+ this.activeCandidate = candidate;
401
+ this.state = this.valid ? "stable" : this.state === "aborted" ? "aborted" : "first-frame";
402
+ this.lastFailure = void 0;
403
+ return ok(candidate);
404
+ }
405
+ commitFrame(candidate) {
406
+ if (this.activeCandidate !== candidate) {
407
+ return err(
408
+ failure(
409
+ "ssr-history-not-active",
410
+ "commit the candidate returned by beginFrame",
411
+ "keep one candidate from beginFrame until the shared queue submit succeeds"
412
+ )
413
+ );
414
+ }
415
+ this.readIndex = candidate.writeSlot;
416
+ this.valid = true;
417
+ this.activeCandidate = void 0;
418
+ this.state = "stable";
419
+ this.resetReason = void 0;
420
+ this.lastFailure = void 0;
421
+ return ok(void 0);
422
+ }
423
+ abortFrame(candidate, stage) {
424
+ if (this.activeCandidate !== candidate) return;
425
+ this.activeCandidate = void 0;
426
+ this.state = "aborted";
427
+ this.lastFailure = stage;
428
+ }
429
+ reset(reason) {
430
+ this.activeCandidate = void 0;
431
+ this.valid = false;
432
+ this.readIndex = 0;
433
+ this.resetReason = reason;
434
+ this.lastFailure = void 0;
435
+ this.resetCount += 1;
436
+ if (this.activeResources !== void 0) this.state = "reset";
437
+ }
438
+ resize(width, height) {
439
+ const next = createResources(
440
+ this.device,
441
+ this.scope,
442
+ positiveDimension(width, "width"),
443
+ positiveDimension(height, "height")
444
+ );
445
+ if (!next.ok) return next;
446
+ if (this.activeResources !== void 0) this.retiringResources.add(this.activeResources);
447
+ this.activeResources = next.value;
448
+ this.activeCandidate = void 0;
449
+ this.valid = false;
450
+ this.readIndex = 0;
451
+ this.resetReason = "resize";
452
+ this.lastFailure = void 0;
453
+ this.resetCount += 1;
454
+ this.state = "reset";
455
+ return ok(void 0);
456
+ }
457
+ /** Retire pending allocations after the queue's already-submitted work. */
458
+ retireAfterFence(queue, onFailure) {
459
+ if (this.retirementFencePending) return;
460
+ if (this.retiringResources.size === 0 && this.activeResources !== void 0) {
461
+ this.retiringResources.add(this.activeResources);
462
+ this.activeCandidate = void 0;
463
+ this.valid = false;
464
+ this.state = "retiring";
465
+ }
466
+ const pending = [...this.retiringResources];
467
+ for (const resources of pending) resources.childScope.beginRetire();
468
+ if (pending.length === 0) return;
469
+ this.retirementFencePending = true;
470
+ const finish = () => {
471
+ this.retirementFencePending = false;
472
+ for (const resources of pending) {
473
+ this.retiringResources.delete(resources);
474
+ resources.childScope.retire();
475
+ if (this.activeResources === resources) this.activeResources = void 0;
476
+ }
477
+ if (this.activeResources === void 0 && this.retiringResources.size === 0) {
478
+ this.state = "retired";
479
+ }
480
+ if (this.retiringResources.size > 0) this.retireAfterFence(queue, onFailure);
481
+ };
482
+ void queue.onSubmittedWorkDone().then(finish, (cause) => {
483
+ onFailure(cause);
484
+ finish();
485
+ });
486
+ }
487
+ retire() {
488
+ this.retirementFencePending = false;
489
+ this.activeCandidate = void 0;
490
+ if (this.activeResources !== void 0) {
491
+ this.activeResources.childScope.retire();
492
+ this.activeResources = void 0;
493
+ }
494
+ for (const resources of this.retiringResources) resources.childScope.retire();
495
+ this.retiringResources.clear();
496
+ this.valid = false;
497
+ this.state = "retired";
498
+ }
499
+ dispose() {
500
+ if (this.state === "disposed") return;
501
+ this.retire();
502
+ this.state = "disposed";
503
+ }
504
+ inspect() {
505
+ const active = this.activeResources;
506
+ return Object.freeze({
507
+ state: this.state,
508
+ width: active?.width ?? 0,
509
+ height: active?.height ?? 0,
510
+ halfWidth: active?.halfWidth ?? 0,
511
+ halfHeight: active?.halfHeight ?? 0,
512
+ format: SSR_HISTORY_FORMAT,
513
+ historyCount: active === void 0 ? 0 : 2,
514
+ historyValid: this.valid,
515
+ readSlot: active === void 0 ? null : this.valid ? this.readIndex : null,
516
+ writeSlot: active === void 0 ? 0 : this.valid ? this.readIndex === 0 ? 1 : 0 : 0,
517
+ activeBytes: active?.bytes ?? 0,
518
+ candidateBytes: 0,
519
+ retiringBytes: [...this.retiringResources].filter((entry) => entry !== active).reduce((sum, entry) => sum + entry.bytes, 0),
520
+ resetCount: this.resetCount,
521
+ resetReason: this.resetReason,
522
+ lastFailure: this.lastFailure
523
+ });
524
+ }
525
+ };
526
+ function createSsrHistoryOwner(input) {
527
+ return SsrHistoryOwner.create(input);
528
+ }
90
529
 
91
530
  // src/scene/visibility/occlusion-query-pool.ts
92
531
  var OCCLUSION_QUERY_PAGE_COUNT = 3;
@@ -229,7 +668,7 @@ function createOcclusionQueryResources(device, pageIndex) {
229
668
  device.destroyQuerySet(querySet.value);
230
669
  return stagingBuffer;
231
670
  }
232
- return ok({
671
+ return ok$1({
233
672
  pageIndex,
234
673
  querySet: querySet.value,
235
674
  resolveBuffer: resolveBuffer.value,
@@ -238,7 +677,7 @@ function createOcclusionQueryResources(device, pageIndex) {
238
677
  }
239
678
  function recordOcclusionResolve(encoder, resources, firstQuery, queryCount) {
240
679
  if (!Number.isSafeInteger(firstQuery) || !Number.isSafeInteger(queryCount) || firstQuery < 0 || queryCount <= 0 || firstQuery + queryCount > OCCLUSION_QUERY_PAGE_INDEX_LIMIT) {
241
- return err(
680
+ return err$1(
242
681
  new RhiError({
243
682
  code: "webgpu-runtime-error",
244
683
  expected: "query range stays within one 4096-index page",
@@ -255,7 +694,7 @@ function recordOcclusionResolve(encoder, resources, firstQuery, queryCount) {
255
694
  );
256
695
  if (!resolved.ok) return resolved;
257
696
  encoder.copyBufferToBuffer(resources.resolveBuffer, resources.stagingBuffer, queryCount * 8);
258
- return ok(void 0);
697
+ return ok$1(void 0);
259
698
  }
260
699
 
261
700
  // src/scene/visibility/types.ts
@@ -310,19 +749,19 @@ var OcclusionRenderRuntime = class {
310
749
  },
311
750
  encodeProxyBounds: (pass) => {
312
751
  const pending = runtime.pendingFrame;
313
- return pending === void 0 ? err(runtimeError("the current RenderSystem frame owns the occlusion candidate")) : runtime.encodeProxyBounds(pass, pending);
752
+ return pending === void 0 ? err$1(runtimeError("the current RenderSystem frame owns the occlusion candidate")) : runtime.encodeProxyBounds(pass, pending);
314
753
  },
315
754
  beginCandidate: (pass) => {
316
755
  const pending = runtime.pendingFrame;
317
756
  if (pending === void 0 || pending.endedCount >= pending.reservations.length) {
318
- return err(runtimeError("the current RenderSystem frame owns the occlusion candidate"));
757
+ return err$1(runtimeError("the current RenderSystem frame owns the occlusion candidate"));
319
758
  }
320
759
  return pass.beginOcclusionQuery(pending.reservations[pending.endedCount]?.queryIndex ?? 0);
321
760
  },
322
761
  endCandidate: (pass) => {
323
762
  const pending = runtime.pendingFrame;
324
763
  if (pending === void 0 || pending.endedCount >= pending.reservations.length) {
325
- return err(runtimeError("the current RenderSystem frame owns the occlusion candidate"));
764
+ return err$1(runtimeError("the current RenderSystem frame owns the occlusion candidate"));
326
765
  }
327
766
  const ended = pass.endOcclusionQuery();
328
767
  if (ended.ok) pending.endedCount += 1;
@@ -331,7 +770,7 @@ var OcclusionRenderRuntime = class {
331
770
  recordResolve: (encoder) => {
332
771
  const pending = runtime.pendingFrame;
333
772
  if (pending === void 0 || pending.endedCount !== pending.reservations.length) {
334
- return err(runtimeError("the real geometry pass must end its occlusion query first"));
773
+ return err$1(runtimeError("the real geometry pass must end its occlusion query first"));
335
774
  }
336
775
  return recordOcclusionResolve(
337
776
  encoder,
@@ -665,7 +1104,7 @@ var OcclusionRenderRuntime = class {
665
1104
  }
666
1105
  encodeProxyBounds(pass, pending) {
667
1106
  if (pending.proxyFloatCount === 0) {
668
- return err(runtimeError("every occlusion candidate needs conservative proxy geometry"));
1107
+ return err$1(runtimeError("every occlusion candidate needs conservative proxy geometry"));
669
1108
  }
670
1109
  const pipeline = this.ensureProxyPipeline(pending.sampleCount);
671
1110
  if (pipeline === void 0) {
@@ -676,11 +1115,11 @@ var OcclusionRenderRuntime = class {
676
1115
  if (!ended.ok) return ended;
677
1116
  }
678
1117
  pending.endedCount = pending.reservations.length;
679
- return ok(void 0);
1118
+ return ok$1(void 0);
680
1119
  }
681
1120
  const buffer = this.ensureProxyBuffer(pending.proxyFloatCount * Float32Array.BYTES_PER_ELEMENT);
682
1121
  if (buffer === void 0) {
683
- return err(runtimeError("the backend must allocate the bounded proxy geometry buffer"));
1122
+ return err$1(runtimeError("the backend must allocate the bounded proxy geometry buffer"));
684
1123
  }
685
1124
  const uploaded = this.device.queue.writeBuffer(
686
1125
  buffer,
@@ -702,7 +1141,7 @@ var OcclusionRenderRuntime = class {
702
1141
  vertexOffset += vertices.length;
703
1142
  }
704
1143
  pending.endedCount = pending.reservations.length;
705
- return ok(void 0);
1144
+ return ok$1(void 0);
706
1145
  }
707
1146
  ensureProxyBuffer(byteLength) {
708
1147
  if (this.proxyBuffer !== void 0) return this.proxyBuffer;
@@ -909,27 +1348,27 @@ function freezeFog(candidate) {
909
1348
  }
910
1349
  function selectEnvironment(input) {
911
1350
  if (input.environments.length > 1) {
912
- return err$1(
1351
+ return err(
913
1352
  new EnvironmentSourceConflictError(
914
1353
  [...input.environments].sort((left, right) => left.entityKey - right.entityKey).map(({ kind, entityKey, sourceKey }) => ({ kind, entityKey, sourceKey }))
915
1354
  )
916
1355
  );
917
1356
  }
918
- if (input.fogs.length > 1) return err$1(new FogCardinalityError(input.fogs.length));
1357
+ if (input.fogs.length > 1) return err(new FogCardinalityError(input.fogs.length));
919
1358
  const selectedFog = input.fogs[0];
920
1359
  if (selectedFog !== void 0) {
921
1360
  const issue = validateFogParameters(selectedFog);
922
1361
  if (issue !== void 0) {
923
- return err$1(new EnvironmentSelectionParameterError(issue.field, issue.value, issue.expected));
1362
+ return err(new EnvironmentSelectionParameterError(issue.field, issue.value, issue.expected));
924
1363
  }
925
1364
  }
926
1365
  const selected = input.environments[0];
927
1366
  if (selected?.kind === "atmosphere") {
928
1367
  const invalid = validateAtmosphereParameters(selected.atmosphere);
929
- if (invalid !== void 0) return err$1(invalid);
1368
+ if (invalid !== void 0) return err(invalid);
930
1369
  }
931
1370
  if (selected?.kind === "atmosphere" && input.suns.length !== 1) {
932
- return err$1(new SunCardinalityError(input.suns.length));
1371
+ return err(new SunCardinalityError(input.suns.length));
933
1372
  }
934
1373
  const source = selected === void 0 ? { kind: "none" } : selected.kind === "atmosphere" ? {
935
1374
  kind: "atmosphere",
@@ -957,7 +1396,7 @@ function selectEnvironment(input) {
957
1396
  sun
958
1397
  };
959
1398
  Object.defineProperty(result, "lane", { value: input.lane, enumerable: false });
960
- return ok$1(Object.freeze(result));
1399
+ return ok(Object.freeze(result));
961
1400
  }
962
1401
 
963
1402
  // src/extract/directional-shadow-projection.ts
@@ -988,208 +1427,6 @@ function projectDirectionalShadow(fits, mapSize, shadowFilter, shadowAngularRadi
988
1427
  }
989
1428
  return { splitPlanes, directionalShadowQuality };
990
1429
  }
991
-
992
- // src/errors/gpu-driven.ts
993
- var ERROR_POLICY = {
994
- "missing-material-receipt": {
995
- expected: "a producer-owned Standard PBR material receipt is present",
996
- hint: "cook and load the Standard PBR artifact, then retry preparation"
997
- },
998
- "missing-uv": {
999
- expected: "the geometry exposes every UV set named by the material receipt",
1000
- hint: "repair the geometry UV semantic or route the draw to the CPU semantic lane"
1001
- },
1002
- "reflection-mismatch": {
1003
- expected: "the loaded reflection receipt matches the artifact layout identity",
1004
- hint: "rebuild the material artifact and reflection from one source, then retry"
1005
- },
1006
- "vertex-input-mismatch": {
1007
- expected: "geometry vertex semantics match the material reflection receipt",
1008
- hint: "repair the geometry vertex semantic layout or route the draw to the CPU lane"
1009
- },
1010
- "alpha-mask-mismatch": {
1011
- expected: "the Alpha Mask cutoff is present in the material receipt",
1012
- hint: "declare alphaCutoff in the Standard PBR material schema and recook it"
1013
- },
1014
- "resource-not-ready": {
1015
- expected: "all material resource slots have resolved handles",
1016
- hint: "resolve the declared texture and sampler resources before recording"
1017
- },
1018
- "stale-generation": {
1019
- expected: "receipt and prepared inputs belong to the requested generation",
1020
- hint: "discard stale GPU facts, rebuild the producer receipt, and retry the same draw"
1021
- },
1022
- "skin-receipt-mismatch": {
1023
- expected: "skinned geometry has a current palette address receipt",
1024
- hint: "rebuild the Skin palette receipt for this generation before recording"
1025
- }
1026
- };
1027
- var GpuDrivenPreparationError = class extends Error {
1028
- code;
1029
- expected;
1030
- hint;
1031
- detail;
1032
- constructor(code, detail) {
1033
- const policy = ERROR_POLICY[code];
1034
- super(`[GpuDrivenPreparationError ${code}] ${policy.expected}`);
1035
- this.name = "GpuDrivenPreparationError";
1036
- this.code = code;
1037
- this.expected = policy.expected;
1038
- this.hint = policy.hint;
1039
- this.detail = detail;
1040
- }
1041
- };
1042
-
1043
- // src/gpu-driven/prepared-draw.ts
1044
- function failure(code, detail) {
1045
- return { ok: false, error: new GpuDrivenPreparationError(code, detail) };
1046
- }
1047
- function sameVertexInputs(expected, actual) {
1048
- return expected.length === actual.length && expected.every(
1049
- (input, index) => input.semantic === actual[index]?.semantic && input.location === actual[index]?.location && input.format === actual[index]?.format
1050
- );
1051
- }
1052
- function hasMaterialResources(snapshot, receipt) {
1053
- const textures = snapshot.material.textureHandles;
1054
- const samplers = snapshot.material.samplerHandles;
1055
- return receipt.resourceSlots.every((slot) => {
1056
- const handles = slot.kind === "texture" ? textures : samplers;
1057
- return handles?.has(slot.parameter) === true;
1058
- });
1059
- }
1060
- function prepareGpuDrivenDraw(input) {
1061
- const receipt = input.artifact.receipt;
1062
- if (receipt === void 0) {
1063
- return failure("missing-material-receipt", {
1064
- reason: "material-receipt-missing",
1065
- owner: "material",
1066
- expected: "MaterialShaderArtifact.receipt"
1067
- });
1068
- }
1069
- if (receipt.generation !== input.generation) {
1070
- return failure("stale-generation", {
1071
- reason: "generation-stale",
1072
- owner: "generation",
1073
- expectedGeneration: input.generation,
1074
- actualGeneration: receipt.generation
1075
- });
1076
- }
1077
- if (receipt.reflection.layoutIdentity !== input.artifact.layoutIdentity) {
1078
- return failure("reflection-mismatch", {
1079
- reason: "reflection-receipt-mismatch",
1080
- owner: "material",
1081
- expected: input.artifact.layoutIdentity,
1082
- actual: receipt.reflection.layoutIdentity
1083
- });
1084
- }
1085
- if (receipt.uvSets.some((uv) => uv.set > 0) && input.geometry.vertexInputs.length < 3) {
1086
- return failure("missing-uv", {
1087
- reason: "uv-set-missing",
1088
- owner: "geometry",
1089
- expected: `${receipt.uvSets.length} material UV sets`,
1090
- actual: `${input.geometry.vertexInputs.filter((vertex) => vertex.semantic.startsWith("uv")).length} geometry UV sets`
1091
- });
1092
- }
1093
- if (!sameVertexInputs(receipt.vertexInputs, input.geometry.vertexInputs)) {
1094
- return failure("vertex-input-mismatch", {
1095
- reason: "vertex-semantic-mismatch",
1096
- owner: "geometry",
1097
- expected: receipt.vertexInputs.map((input2) => input2.semantic).join(","),
1098
- actual: input.geometry.vertexInputs.map((input2) => input2.semantic).join(",")
1099
- });
1100
- }
1101
- if (receipt.alphaMask.cutoff.length === 0) {
1102
- return failure("alpha-mask-mismatch", {
1103
- reason: "alpha-mask-receipt-missing",
1104
- owner: "material",
1105
- expected: "alphaMask.cutoff"
1106
- });
1107
- }
1108
- if (!hasMaterialResources(input.snapshot, receipt)) {
1109
- return failure("resource-not-ready", {
1110
- reason: "material-resource-missing",
1111
- owner: "material",
1112
- expected: receipt.resourceSlots.map((slot) => slot.parameter).join(",")
1113
- });
1114
- }
1115
- const deformation = input.snapshot.skin === void 0 ? "rigid" : "skin";
1116
- if (deformation === "skin") {
1117
- if (input.skinReceipt === void 0 || receipt.skinPaletteAddress === void 0) {
1118
- return failure("skin-receipt-mismatch", {
1119
- reason: "skin-address-missing",
1120
- owner: "skin",
1121
- expected: "skinPaletteAddress and skinReceipt"
1122
- });
1123
- }
1124
- if (input.skinReceipt.generation !== input.generation || input.skinReceipt.group !== receipt.skinPaletteAddress.group || input.skinReceipt.binding !== receipt.skinPaletteAddress.binding) {
1125
- return failure("skin-receipt-mismatch", {
1126
- reason: "skin-address-missing",
1127
- owner: "skin",
1128
- expected: `${receipt.skinPaletteAddress.group}:${receipt.skinPaletteAddress.binding}@${input.generation}`,
1129
- actual: `${input.skinReceipt.group}:${input.skinReceipt.binding}@${input.skinReceipt.generation}`
1130
- });
1131
- }
1132
- }
1133
- return {
1134
- ok: true,
1135
- value: {
1136
- identity: {
1137
- material: input.artifact.material,
1138
- geometry: input.geometry.identity,
1139
- deformation
1140
- },
1141
- receiptGeneration: receipt.generation,
1142
- directEntry: receipt.directEntry,
1143
- sceneIndexEntry: receipt.sceneIndexEntry,
1144
- materialRow: receipt.materialRow,
1145
- resourceSlots: receipt.resourceSlots,
1146
- uvSets: receipt.uvSets,
1147
- vertexInputs: receipt.vertexInputs,
1148
- alphaMask: receipt.alphaMask,
1149
- skinPaletteAddress: receipt.skinPaletteAddress,
1150
- topology: input.draw.topology,
1151
- indexed: input.draw.kind === "indexed",
1152
- first: input.draw.first,
1153
- count: input.draw.count,
1154
- baseVertex: input.draw.baseVertex
1155
- }
1156
- };
1157
- }
1158
-
1159
- // src/extract/gpu-driven.ts
1160
- function resolvePreparedGpuDrivenDraw(input) {
1161
- return prepareGpuDrivenDraw(input);
1162
- }
1163
- function gpuDrivenMaterialResourceClass(material) {
1164
- const textures = [...material.textureHandles?.entries() ?? []].map(([name, handle]) => [name, Number(handle)]).sort(([left], [right]) => left.localeCompare(right));
1165
- const samplers = [...material.samplerHandles?.entries() ?? []].map(([name, handle]) => [name, Number(handle)]).sort(([left], [right]) => left.localeCompare(right));
1166
- return JSON.stringify({
1167
- textures,
1168
- samplers,
1169
- video: [...material.videoTextureFields?.keys() ?? []].sort()
1170
- });
1171
- }
1172
- function buildGpuDrivenDraws(input) {
1173
- let nonIndexedFirst = 0;
1174
- return input.submeshes.flatMap((submesh) => {
1175
- const drawMaterial = input.materials[submesh.materialSlot] ?? input.fallbackMaterial;
1176
- const first = input.indexed ? submesh.indexOffset : nonIndexedFirst;
1177
- nonIndexedFirst += submesh.vertexCount;
1178
- if (drawMaterial.transparent === true) return [];
1179
- const draw = {
1180
- kind: input.indexed ? "indexed" : "non-indexed",
1181
- first,
1182
- count: input.indexed ? submesh.indexCount : submesh.vertexCount,
1183
- baseVertex: 0,
1184
- materialSlot: submesh.materialSlot,
1185
- topology: submesh.topology,
1186
- pipelineClass: `${drawMaterial.materialShaderId ?? "forgeax::default-unlit"}|${submesh.topology}|${JSON.stringify(drawMaterial.renderState ?? null)}`,
1187
- materialResourceClass: gpuDrivenMaterialResourceClass(drawMaterial)
1188
- };
1189
- const prepared = input.prepare?.(draw, drawMaterial);
1190
- return [prepared === void 0 ? draw : { ...draw, prepared }];
1191
- });
1192
- }
1193
1430
  var bakeCache = /* @__PURE__ */ new WeakMap();
1194
1431
  var materialCache = /* @__PURE__ */ new WeakMap();
1195
1432
  var liveGlyphSlots = /* @__PURE__ */ new WeakMap();
@@ -1252,8 +1489,8 @@ function glyphTextLayoutSystem(world, gpuStore) {
1252
1489
  const error = processEntity(world, gpuStore, entity);
1253
1490
  if (error !== null && firstError === null) firstError = error;
1254
1491
  }
1255
- if (firstError !== null) return err$1(firstError);
1256
- return ok$1(void 0);
1492
+ if (firstError !== null) return err(firstError);
1493
+ return ok(void 0);
1257
1494
  }
1258
1495
  function collectGlyphEntities(world) {
1259
1496
  const entities = [];
@@ -1421,13 +1658,15 @@ function signatureOf(gt) {
1421
1658
  function asFontHandle(raw) {
1422
1659
  return toShared(raw);
1423
1660
  }
1661
+
1662
+ // src/instances-derived-bounds.ts
1663
+ var fingerprintScalar = new Float32Array(1);
1664
+ var fingerprintBits = new Uint32Array(fingerprintScalar.buffer);
1424
1665
  function fingerprintNumericArray(values) {
1425
1666
  let hash = 2166136261;
1426
- const scalar = new Float32Array(1);
1427
- const bits = new Uint32Array(scalar.buffer);
1428
1667
  for (let index = 0; index < values.length; index += 1) {
1429
- scalar[0] = Number(values[index]);
1430
- hash = Math.imul(hash ^ (bits[0] ?? 0), 16777619) >>> 0;
1668
+ fingerprintScalar[0] = Number(values[index]);
1669
+ hash = Math.imul(hash ^ (fingerprintBits[0] ?? 0), 16777619) >>> 0;
1431
1670
  }
1432
1671
  return hash >>> 0;
1433
1672
  }
@@ -1448,14 +1687,128 @@ function finiteMatrix(matrix) {
1448
1687
  }
1449
1688
  return true;
1450
1689
  }
1451
- function includeBox(out, candidate) {
1452
- for (const x of [candidate[0], candidate[3]]) {
1453
- for (const y of [candidate[1], candidate[4]]) {
1454
- for (const z of [candidate[2], candidate[5]]) {
1455
- box3.expandByPoint(out, [x, y, z]);
1456
- }
1457
- }
1690
+ function multiplyMat4(out, left, right, rightOffset = 0) {
1691
+ for (let column = 0; column < 4; column += 1) {
1692
+ const rightColumn = rightOffset + column * 4;
1693
+ const right0 = Number(right[rightColumn] ?? 0);
1694
+ const right1 = Number(right[rightColumn + 1] ?? 0);
1695
+ const right2 = Number(right[rightColumn + 2] ?? 0);
1696
+ const right3 = Number(right[rightColumn + 3] ?? 0);
1697
+ const outOffset = column * 4;
1698
+ out[outOffset] = Number(left[0] ?? 0) * right0 + Number(left[4] ?? 0) * right1 + Number(left[8] ?? 0) * right2 + Number(left[12] ?? 0) * right3;
1699
+ out[outOffset + 1] = Number(left[1] ?? 0) * right0 + Number(left[5] ?? 0) * right1 + Number(left[9] ?? 0) * right2 + Number(left[13] ?? 0) * right3;
1700
+ out[outOffset + 2] = Number(left[2] ?? 0) * right0 + Number(left[6] ?? 0) * right1 + Number(left[10] ?? 0) * right2 + Number(left[14] ?? 0) * right3;
1701
+ out[outOffset + 3] = Number(left[3] ?? 0) * right0 + Number(left[7] ?? 0) * right1 + Number(left[11] ?? 0) * right2 + Number(left[15] ?? 0) * right3;
1702
+ }
1703
+ }
1704
+ function finiteMatrixAt(values, offset) {
1705
+ if (values.length - offset < 16) return false;
1706
+ for (let index = 0; index < 16; index += 1) {
1707
+ if (!Number.isFinite(values[offset + index])) return false;
1708
+ }
1709
+ return true;
1710
+ }
1711
+ function isAffine(matrix) {
1712
+ return matrix[3] === 0 && matrix[7] === 0 && matrix[11] === 0 && matrix[15] === 1;
1713
+ }
1714
+ function includeBox(out, candidate, initialized) {
1715
+ const minX = candidate[0];
1716
+ const minY = candidate[1];
1717
+ const minZ = candidate[2];
1718
+ const maxX = candidate[3];
1719
+ const maxY = candidate[4];
1720
+ const maxZ = candidate[5];
1721
+ if (!initialized) {
1722
+ out[0] = minX;
1723
+ out[1] = minY;
1724
+ out[2] = minZ;
1725
+ out[3] = maxX;
1726
+ out[4] = maxY;
1727
+ out[5] = maxZ;
1728
+ return true;
1458
1729
  }
1730
+ if (minX < (out[0] ?? Number.POSITIVE_INFINITY)) out[0] = minX;
1731
+ if (minY < (out[1] ?? Number.POSITIVE_INFINITY)) out[1] = minY;
1732
+ if (minZ < (out[2] ?? Number.POSITIVE_INFINITY)) out[2] = minZ;
1733
+ if (maxX > (out[3] ?? Number.NEGATIVE_INFINITY)) out[3] = maxX;
1734
+ if (maxY > (out[4] ?? Number.NEGATIVE_INFINITY)) out[4] = maxY;
1735
+ if (maxZ > (out[5] ?? Number.NEGATIVE_INFINITY)) out[5] = maxZ;
1736
+ return true;
1737
+ }
1738
+ function transformAabb(out, local, matrix) {
1739
+ const minX = local[0];
1740
+ const minY = local[1];
1741
+ const minZ = local[2];
1742
+ const maxX = local[3];
1743
+ const maxY = local[4];
1744
+ const maxZ = local[5];
1745
+ const centerX = (minX + maxX) * 0.5;
1746
+ const centerY = (minY + maxY) * 0.5;
1747
+ const centerZ = (minZ + maxZ) * 0.5;
1748
+ const extentX = (maxX - minX) * 0.5;
1749
+ const extentY = (maxY - minY) * 0.5;
1750
+ const extentZ = (maxZ - minZ) * 0.5;
1751
+ if (isAffine(matrix)) {
1752
+ const centerWorldX = matrix[0] * centerX + matrix[4] * centerY + matrix[8] * centerZ + matrix[12];
1753
+ const centerWorldY = matrix[1] * centerX + matrix[5] * centerY + matrix[9] * centerZ + matrix[13];
1754
+ const centerWorldZ = matrix[2] * centerX + matrix[6] * centerY + matrix[10] * centerZ + matrix[14];
1755
+ const extentWorldX = Math.abs(matrix[0]) * extentX + Math.abs(matrix[4]) * extentY + Math.abs(matrix[8]) * extentZ;
1756
+ const extentWorldY = Math.abs(matrix[1]) * extentX + Math.abs(matrix[5]) * extentY + Math.abs(matrix[9]) * extentZ;
1757
+ const extentWorldZ = Math.abs(matrix[2]) * extentX + Math.abs(matrix[6]) * extentY + Math.abs(matrix[10]) * extentZ;
1758
+ out[0] = centerWorldX - extentWorldX;
1759
+ out[1] = centerWorldY - extentWorldY;
1760
+ out[2] = centerWorldZ - extentWorldZ;
1761
+ out[3] = centerWorldX + extentWorldX;
1762
+ out[4] = centerWorldY + extentWorldY;
1763
+ out[5] = centerWorldZ + extentWorldZ;
1764
+ return finiteAabb(out);
1765
+ }
1766
+ let minimumW = Number.POSITIVE_INFINITY;
1767
+ let maximumW = Number.NEGATIVE_INFINITY;
1768
+ for (let corner = 0; corner < 8; corner += 1) {
1769
+ const x = (corner & 1) === 0 ? minX : maxX;
1770
+ const y = (corner & 2) === 0 ? minY : maxY;
1771
+ const z = (corner & 4) === 0 ? minZ : maxZ;
1772
+ const w = matrix[3] * x + matrix[7] * y + matrix[11] * z + matrix[15];
1773
+ if (!Number.isFinite(w)) return false;
1774
+ if (w < minimumW) minimumW = w;
1775
+ if (w > maximumW) maximumW = w;
1776
+ }
1777
+ if (minimumW <= 0 && maximumW >= 0) return false;
1778
+ let unionMinX = Number.POSITIVE_INFINITY;
1779
+ let unionMinY = Number.POSITIVE_INFINITY;
1780
+ let unionMinZ = Number.POSITIVE_INFINITY;
1781
+ let unionMaxX = Number.NEGATIVE_INFINITY;
1782
+ let unionMaxY = Number.NEGATIVE_INFINITY;
1783
+ let unionMaxZ = Number.NEGATIVE_INFINITY;
1784
+ for (let corner = 0; corner < 8; corner += 1) {
1785
+ const x = (corner & 1) === 0 ? minX : maxX;
1786
+ const y = (corner & 2) === 0 ? minY : maxY;
1787
+ const z = (corner & 4) === 0 ? minZ : maxZ;
1788
+ const rawX = matrix[0] * x + matrix[4] * y + matrix[8] * z + matrix[12];
1789
+ const rawY = matrix[1] * x + matrix[5] * y + matrix[9] * z + matrix[13];
1790
+ const rawZ = matrix[2] * x + matrix[6] * y + matrix[10] * z + matrix[14];
1791
+ const w = matrix[3] * x + matrix[7] * y + matrix[11] * z + matrix[15];
1792
+ const projectedX = rawX / w;
1793
+ const projectedY = rawY / w;
1794
+ const projectedZ = rawZ / w;
1795
+ if (!Number.isFinite(projectedX) || !Number.isFinite(projectedY) || !Number.isFinite(projectedZ)) {
1796
+ return false;
1797
+ }
1798
+ if (projectedX < unionMinX) unionMinX = projectedX;
1799
+ if (projectedY < unionMinY) unionMinY = projectedY;
1800
+ if (projectedZ < unionMinZ) unionMinZ = projectedZ;
1801
+ if (projectedX > unionMaxX) unionMaxX = projectedX;
1802
+ if (projectedY > unionMaxY) unionMaxY = projectedY;
1803
+ if (projectedZ > unionMaxZ) unionMaxZ = projectedZ;
1804
+ }
1805
+ out[0] = unionMinX;
1806
+ out[1] = unionMinY;
1807
+ out[2] = unionMinZ;
1808
+ out[3] = unionMaxX;
1809
+ out[4] = unionMaxY;
1810
+ out[5] = unionMaxZ;
1811
+ return finiteAabb(out);
1459
1812
  }
1460
1813
  function deriveInstancesUnionBounds(input) {
1461
1814
  const { meshAabb, entityWorld, transforms } = input;
@@ -1463,40 +1816,36 @@ function deriveInstancesUnionBounds(input) {
1463
1816
  return void 0;
1464
1817
  }
1465
1818
  if (transforms.length === 0 || transforms.length % 16 !== 0) return void 0;
1466
- const local = box3.create(
1467
- meshAabb[0],
1468
- meshAabb[1],
1469
- meshAabb[2],
1470
- meshAabb[3],
1471
- meshAabb[4],
1472
- meshAabb[5]
1473
- );
1474
- const union = box3.create();
1475
- const composed = mat4.create();
1476
- const transformed = box3.create();
1819
+ const local = meshAabb;
1820
+ const union = new Float32Array(6);
1821
+ const composed = new Float32Array(16);
1822
+ const transformed = new Float32Array(6);
1823
+ let initialized = false;
1477
1824
  for (let offset = 0; offset < transforms.length; offset += 16) {
1478
- const instance = new Float32Array(16);
1479
- for (let lane = 0; lane < 16; lane += 1) {
1480
- instance[lane] = transforms[offset + lane];
1481
- }
1482
- if (!finiteMatrix(instance)) return void 0;
1483
- mat4.multiply(composed, entityWorld, instance);
1484
- box3.transformBox3(transformed, local, composed);
1485
- if (!finiteAabb(transformed)) return void 0;
1486
- includeBox(union, transformed);
1825
+ if (!finiteMatrixAt(transforms, offset)) return void 0;
1826
+ multiplyMat4(composed, entityWorld, transforms, offset);
1827
+ if (!finiteMatrix(composed) || !transformAabb(transformed, local, composed)) return void 0;
1828
+ initialized = includeBox(union, transformed, initialized);
1487
1829
  }
1488
- return new Float32Array(union);
1830
+ return initialized && finiteAabb(union) ? union : void 0;
1489
1831
  }
1490
1832
  var InstanceBoundsCache = class {
1491
1833
  entries = /* @__PURE__ */ new Map();
1834
+ hits = 0;
1835
+ misses = 0;
1836
+ derives = 0;
1837
+ invalidations = 0;
1492
1838
  key(input) {
1493
1839
  return `${input.worldId === void 0 ? "" : `${input.worldId}:`}${input.entityKey}`;
1494
1840
  }
1495
1841
  get(input) {
1496
1842
  const previous = this.entries.get(this.key(input));
1497
1843
  if (previous !== void 0 && previous.meshGeneration === input.meshGeneration && previous.transformGeneration === input.transformGeneration && previous.matrixGeneration === input.matrixGeneration) {
1844
+ this.hits += 1;
1498
1845
  return previous.bounds;
1499
1846
  }
1847
+ this.misses += 1;
1848
+ this.derives += 1;
1500
1849
  const bounds = deriveInstancesUnionBounds(input);
1501
1850
  this.entries.set(this.key(input), {
1502
1851
  ...input.worldId === void 0 ? {} : { worldId: input.worldId },
@@ -1510,11 +1859,22 @@ var InstanceBoundsCache = class {
1510
1859
  }
1511
1860
  invalidate(entityKey, worldId) {
1512
1861
  if (entityKey === void 0) {
1862
+ if (this.entries.size > 0) this.invalidations += this.entries.size;
1513
1863
  this.entries.clear();
1514
1864
  } else {
1515
- this.entries.delete(this.key({ entityKey, ...worldId === void 0 ? {} : { worldId } }));
1865
+ if (this.entries.delete(this.key({ entityKey, ...worldId === void 0 ? {} : { worldId } }))) {
1866
+ this.invalidations += 1;
1867
+ }
1516
1868
  }
1517
1869
  }
1870
+ inspect() {
1871
+ return {
1872
+ hits: this.hits,
1873
+ misses: this.misses,
1874
+ derives: this.derives,
1875
+ invalidations: this.invalidations
1876
+ };
1877
+ }
1518
1878
  };
1519
1879
 
1520
1880
  // src/points-lines/bounds.ts
@@ -1602,13 +1962,40 @@ function createCookieProjectionMatrixData(count) {
1602
1962
  }
1603
1963
  return data;
1604
1964
  }
1965
+ function buildShadowFrusta(lights) {
1966
+ const result = [];
1967
+ const add = (matrix) => {
1968
+ result.push(frustum.fromViewProjection(frustum.create(), matrix));
1969
+ };
1970
+ for (const matrix of lights.lightViewProj?.slice(0, lights.cascadeCount) ?? []) add(matrix);
1971
+ for (const snapshot of lights.pointShadow) {
1972
+ if (snapshot.shadowAtlasLayer < 0) continue;
1973
+ for (let face = 0; face < 6; face += 1)
1974
+ add(snapshot.shadowMatrices.subarray(face * 16, (face + 1) * 16));
1975
+ }
1976
+ for (const snapshot of lights.spot) {
1977
+ if (snapshot.shadowAtlasTile >= 0 && snapshot.lightViewProj !== void 0)
1978
+ add(snapshot.lightViewProj);
1979
+ }
1980
+ return result;
1981
+ }
1605
1982
 
1606
1983
  // src/render-system-extract-tail.ts
1984
+ function skinPaletteIdentity(world, entity) {
1985
+ return `skin:${world.identity}:${entity}`;
1986
+ }
1607
1987
  function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCachesByWorld, options = {}) {
1608
1988
  const cameraOwner = typeof owner === "number" ? owner : owner.cameraOwner;
1609
1989
  const resourceOwner = typeof owner === "number" ? owner : owner.resourceOwner;
1990
+ const cameraEntityKey = typeof owner === "number" ? void 0 : owner.cameraEntityKey;
1991
+ const renderableRequest = options.renderables ?? "full";
1992
+ const renderableMode = typeof renderableRequest === "object" ? "full" : renderableRequest;
1993
+ const partialEntitiesByWorld = typeof renderableRequest === "object" ? renderableRequest.entitiesByWorld : void 0;
1994
+ const retainHidden = options.retainHidden ?? typeof renderableRequest === "object";
1610
1995
  const skinPaletteAllocator = pipelineState?.skinPaletteAllocator ?? null;
1611
- if (skinPaletteAllocator !== null) {
1996
+ const reconcileSkinFrame = renderableRequest === "full";
1997
+ if (skinPaletteAllocator !== null && reconcileSkinFrame) {
1998
+ skinPaletteAllocator.beginFrame();
1612
1999
  skinPaletteAllocator.resetForFrame();
1613
2000
  }
1614
2001
  const failedWorlds = /* @__PURE__ */ new Set();
@@ -1626,6 +2013,13 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1626
2013
  const world = worlds[wi];
1627
2014
  if (world === void 0 || failedWorlds.has(world)) continue;
1628
2015
  try {
2016
+ if (skinPaletteAllocator !== null && partialEntitiesByWorld !== void 0) {
2017
+ for (const entityKey of partialEntitiesByWorld[wi] ?? []) {
2018
+ if (!world.hasComponent(entityKey, Skin)) {
2019
+ skinPaletteAllocator.releasePersistentSlice(skinPaletteIdentity(world, entityKey));
2020
+ }
2021
+ }
2022
+ }
1629
2023
  const isCameraOwner = wi === cameraOwner;
1630
2024
  const cameraOwnerFrame2 = framesByWorld.get(cameraOwner);
1631
2025
  const prepared = prepareExtractContext(world, {
@@ -1641,18 +2035,20 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1641
2035
  },
1642
2036
  ...options.materialContext === void 0 ? {} : { materialContext: options.materialContext },
1643
2037
  cull: options.cull === "none" ? "none" : isCameraOwner ? "self" : "external",
1644
- renderables: options.renderables ?? "full",
1645
- ...options.renderableEntitiesByWorld?.[wi] === void 0 ? {} : { renderableEntities: options.renderableEntitiesByWorld[wi] },
1646
- retainHidden: options.retainHidden ?? false,
2038
+ renderables: renderableMode,
2039
+ ...isCameraOwner && cameraEntityKey !== void 0 ? { cameraEntityKey } : {},
2040
+ ...partialEntitiesByWorld?.[wi] === void 0 ? {} : { renderableEntities: partialEntitiesByWorld[wi] },
2041
+ retainHidden,
2042
+ worldId: wi,
1647
2043
  ...options.getMaterialShaderArtifact === void 0 ? {} : { getMaterialShaderArtifact: options.getMaterialShaderArtifact },
1648
2044
  ...options.instanceCollections === void 0 ? {} : { instanceCollections: options.instanceCollections },
1649
2045
  ...cameraOwnerFrame2 === void 0 ? {} : { cullCameras: cameraOwnerFrame2.cameras }
1650
2046
  });
1651
2047
  const frame = extractFrame(world, prepared);
1652
2048
  framesByWorld.set(wi, frame);
1653
- } catch (err6) {
2049
+ } catch (err8) {
1654
2050
  try {
1655
- createWorldInternalView(world)._routeError(err6, {
2051
+ createWorldInternalView(world)._routeError(err8, {
1656
2052
  severity: Severity.Error,
1657
2053
  systemName: `RenderSystem.extractFrames(world[${wi}])`
1658
2054
  });
@@ -1660,6 +2056,9 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1660
2056
  }
1661
2057
  }
1662
2058
  }
2059
+ if (skinPaletteAllocator !== null && reconcileSkinFrame) {
2060
+ skinPaletteAllocator.endFrame();
2061
+ }
1663
2062
  for (let wi = 0; wi < worlds.length; wi++) {
1664
2063
  const frame = framesByWorld.get(wi);
1665
2064
  if (frame === void 0) continue;
@@ -1668,6 +2067,9 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1668
2067
  }
1669
2068
  const renderables = [];
1670
2069
  const dispatchEntries = [];
2070
+ const shadowCasterEntityKeys = /* @__PURE__ */ new Set();
2071
+ const shadowCasterDrawKeys = /* @__PURE__ */ new Set();
2072
+ const shadowCasterMembership = /* @__PURE__ */ new Map();
1671
2073
  const visibilitySnapshots = [];
1672
2074
  const featureVisibilitySnapshots = [];
1673
2075
  const hiddenEntityReports = [];
@@ -1694,6 +2096,18 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1694
2096
  for (const d of f.dispatch) {
1695
2097
  dispatchEntries.push({ ...d, renderableIndex: (d.renderableIndex ?? 0) + base });
1696
2098
  }
2099
+ for (const key of f.shadowCasterEntityKeys) shadowCasterEntityKeys.add(key);
2100
+ for (const key of f.shadowCasterDrawKeys) shadowCasterDrawKeys.add(key);
2101
+ for (const membership of f.shadowCasterMembership ?? []) {
2102
+ const rebased = { ...membership, renderableIndex: membership.renderableIndex + base };
2103
+ const key = gpuDrivenShadowDrawKey(
2104
+ rebased.worldEntity,
2105
+ rebased.materialHandle,
2106
+ rebased.drawItemIndex,
2107
+ rebased.passIndex
2108
+ );
2109
+ shadowCasterMembership.set(key, rebased);
2110
+ }
1697
2111
  }
1698
2112
  dispatchEntries.sort((a, b) => (a.queue ?? 0) - (b.queue ?? 0));
1699
2113
  const point = [];
@@ -1713,11 +2127,14 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1713
2127
  const pointShadow = [];
1714
2128
  let directionalCsmConfig;
1715
2129
  let directionalCsmDirection;
1716
- for (const f of succeededFrames) {
1717
- for (const p of f.lights.point) point.push(p);
1718
- for (const s of f.lights.spot) spot.push(s);
2130
+ for (let fi = 0; fi < succeededFrames.length; fi += 1) {
2131
+ const f = succeededFrames[fi];
2132
+ const wId = succeededIndices[fi] ?? 0;
2133
+ if (f === void 0) continue;
2134
+ for (const p of f.lights.point) point.push({ ...p, worldId: wId });
2135
+ for (const s of f.lights.spot) spot.push({ ...s, worldId: wId });
1719
2136
  for (const r of f.lights.rect) rect.push(r);
1720
- for (const ps of f.lights.pointShadow) pointShadow.push(ps);
2137
+ for (const ps of f.lights.pointShadow) pointShadow.push({ ...ps, worldId: wId });
1721
2138
  if (directional === void 0 && f.lights.directional !== void 0) {
1722
2139
  directional = f.lights.directional;
1723
2140
  lightViewProj = f.lights.lightViewProj;
@@ -1740,8 +2157,8 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1740
2157
  if (succeededIndices[fi] === cameraOwner) cameraOwnerFrame = succeededFrames[fi];
1741
2158
  if (succeededIndices[fi] === resourceOwner) resourceOwnerFrame = succeededFrames[fi];
1742
2159
  }
1743
- const cameras = cameraOwnerFrame !== void 0 ? [...cameraOwnerFrame.cameras] : [];
1744
- const auxiliaryCameras = cameraOwnerFrame !== void 0 ? [...cameraOwnerFrame.auxiliaryCameras] : [];
2160
+ const cameras = cameraOwnerFrame?.cameras.map((camera) => ({ ...camera, worldId: cameraOwner })) ?? [];
2161
+ const auxiliaryCameras = cameraOwnerFrame?.auxiliaryCameras.map((camera) => ({ ...camera, worldId: cameraOwner })) ?? [];
1745
2162
  const cubeCameras = cameraOwnerFrame !== void 0 ? [...cameraOwnerFrame.cubeCameras] : [];
1746
2163
  const mergeCam = cameras[0];
1747
2164
  if (directionalCsmConfig !== void 0 && directionalCsmDirection !== void 0) {
@@ -1798,7 +2215,10 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1798
2215
  const fog = resourceOwnerFrame?.fog;
1799
2216
  const fogFailure = resourceOwnerFrame?.fogFailure;
1800
2217
  const environment = resourceOwnerFrame?.environment;
1801
- const lightProbes = succeededFrames.flatMap((frame) => frame.lightProbes ?? []);
2218
+ const lightProbes = succeededFrames.flatMap((frame, index) => {
2219
+ const worldId = succeededIndices[index] ?? 0;
2220
+ return (frame.lightProbes ?? []).map((probe) => ({ ...probe, worldId }));
2221
+ });
1802
2222
  const postProcessParams = new Map(resourceOwnerFrame?.postProcessParams);
1803
2223
  const OUTPUT_TRANSFORM_PARAM_KEY = STANDARD_OUTPUT_TRANSFORM_FEATURE_ID;
1804
2224
  const cameraTonemapParam = cameraOwnerFrame?.postProcessParams.get(OUTPUT_TRANSFORM_PARAM_KEY);
@@ -1814,28 +2234,28 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1814
2234
  const visibilityStats = {
1815
2235
  explicitlyHidden: succeededFrames.reduce((s, f) => s + f.visibilityStats.explicitlyHidden, 0)
1816
2236
  };
2237
+ const materialTextureSources = {
2238
+ sourceFieldsVisited: 0,
2239
+ numericSharedRefProbes: 0,
2240
+ sourceCacheHits: 0,
2241
+ sourceCacheMisses: 0,
2242
+ producerRoutes: {}
2243
+ };
2244
+ for (const frame of succeededFrames) {
2245
+ const stats = frame.materialTextureSources;
2246
+ if (stats === void 0) continue;
2247
+ materialTextureSources.sourceFieldsVisited += stats.sourceFieldsVisited;
2248
+ materialTextureSources.numericSharedRefProbes += stats.numericSharedRefProbes;
2249
+ materialTextureSources.sourceCacheHits += stats.sourceCacheHits;
2250
+ materialTextureSources.sourceCacheMisses += stats.sourceCacheMisses;
2251
+ for (const [route, count] of Object.entries(stats.producerRoutes)) {
2252
+ materialTextureSources.producerRoutes[route] = (materialTextureSources.producerRoutes[route] ?? 0) + count;
2253
+ }
2254
+ }
1817
2255
  const reflectionProbes = succeededFrames.flatMap((f, index) => {
1818
2256
  const worldId = succeededIndices[index] ?? 0;
1819
2257
  return (f.reflectionProbes ?? []).map((probe) => ({ ...probe, worldId }));
1820
2258
  });
1821
- if (options.renderables !== "none" && options.renderableEntitiesByWorld === void 0) {
1822
- options.instanceCollections?.retain(
1823
- new Set(
1824
- renderables.flatMap(
1825
- (row) => row.instances?.collectionId === void 0 ? [] : [row.instances.collectionId]
1826
- )
1827
- )
1828
- );
1829
- if (skinPaletteAllocator !== null && typeof skinPaletteAllocator.retainSliceKeys === "function") {
1830
- skinPaletteAllocator.retainSliceKeys(
1831
- new Set(
1832
- renderables.flatMap(
1833
- (row) => row.skin === void 0 ? [] : [`${worlds[row.worldId]?.identity ?? row.worldId}:${row.entityKey}`]
1834
- )
1835
- )
1836
- );
1837
- }
1838
- }
1839
2259
  return {
1840
2260
  cameras,
1841
2261
  auxiliaryCameras,
@@ -1845,6 +2265,9 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1845
2265
  ...volumetricFog === void 0 ? {} : { volumetricFog: { ...volumetricFog, worldId: resourceOwner } },
1846
2266
  renderables,
1847
2267
  dispatch: dispatchEntries,
2268
+ shadowCasterEntityKeys,
2269
+ shadowCasterDrawKeys,
2270
+ ...shadowCasterMembership.size === 0 ? {} : { shadowCasterMembership: [...shadowCasterMembership.values()] },
1848
2271
  skylight,
1849
2272
  skylightCount,
1850
2273
  lightProbes,
@@ -1856,6 +2279,7 @@ function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCac
1856
2279
  environmentReady: resourceOwnerFrame !== void 0 && environment !== void 0,
1857
2280
  frustumStats,
1858
2281
  visibilityStats,
2282
+ materialTextureSources,
1859
2283
  postProcessParams,
1860
2284
  visibilitySnapshots,
1861
2285
  featureVisibilitySnapshots,
@@ -1898,6 +2322,7 @@ function morphSnapshotFor(mesh, weights) {
1898
2322
  if (!Number.isFinite(weight)) return void 0;
1899
2323
  copied[index] = weight;
1900
2324
  }
2325
+ if (copied.every((weight) => weight === 0)) return void 0;
1901
2326
  return { weights: copied, targetCount: targets.length };
1902
2327
  }
1903
2328
  function extractFrame(world, context) {
@@ -1916,10 +2341,18 @@ function extractFrame(world, context) {
1916
2341
  const fogFailure = fogState(world).failure;
1917
2342
  const visibility = context.visibility.hasAnyHiddenIntent ? context.visibility : void 0;
1918
2343
  const skinPaletteAllocator = pipelineState?.skinPaletteAllocator ?? null;
2344
+ const materialTextureSourceStats = {
2345
+ sourceFieldsVisited: 0,
2346
+ numericSharedRefProbes: 0,
2347
+ sourceCacheHits: 0,
2348
+ sourceCacheMisses: 0,
2349
+ producerRoutes: {}
2350
+ };
2351
+ const materialTextureSourceCache = /* @__PURE__ */ new Map();
1919
2352
  const directionalLightQuery = world.query({ read: [DirectionalLight] }).unwrap();
1920
2353
  const worldInternal = createWorldInternalView(world);
1921
2354
  let volumetricFog = extractVolumeSnapshot(world, assets, worldInternal);
1922
- const cameraRoles = selectCameraRoles(world);
2355
+ const cameraRoles = selectCameraRoles(world, context.cameraEntityKey);
1923
2356
  const cameras = [...cameraRoles.display];
1924
2357
  const auxiliaryCameras = cameraRoles.auxiliary;
1925
2358
  const cubeCameras = collectCubeCameraSnapshots(world);
@@ -1996,6 +2429,7 @@ function extractFrame(world, context) {
1996
2429
  pointSnapshots.push({
1997
2430
  kind: "point",
1998
2431
  entity: entityId,
2432
+ worldId: context.worldId,
1999
2433
  position,
2000
2434
  color: vec3.create(
2001
2435
  (p.color[0] ?? 1) * intensity,
@@ -2129,6 +2563,7 @@ function extractFrame(world, context) {
2129
2563
  spotSnapshots.push({
2130
2564
  kind: "spot",
2131
2565
  entity: row.entity,
2566
+ worldId: context.worldId,
2132
2567
  // D-6: position reflects world transform; direction stays sourced
2133
2568
  // from SpotLight.direction (NOT rotated by the parent).
2134
2569
  position,
@@ -2340,10 +2775,13 @@ function extractFrame(world, context) {
2340
2775
  }
2341
2776
  pointShadowSnapshots.push({
2342
2777
  entity: row.entity,
2778
+ worldId: context.worldId,
2343
2779
  position: lightPos,
2344
2780
  mapSize,
2345
2781
  nearPlane,
2346
2782
  farPlane,
2783
+ depthBias: ps.depthBias,
2784
+ normalBias: ps.normalBias,
2347
2785
  shadowAtlasLayer: layer,
2348
2786
  shadowMatrices: packed
2349
2787
  });
@@ -2386,6 +2824,7 @@ function extractFrame(world, context) {
2386
2824
  directionalCsmConfig,
2387
2825
  directionalCsmDirection
2388
2826
  };
2827
+ const shadowFrusta = cullMode === "none" ? [] : buildShadowFrusta(lights);
2389
2828
  const skylightQuery = world.query({ read: [Skylight] }).unwrap();
2390
2829
  let skylight;
2391
2830
  let skylightCount = 0;
@@ -2432,6 +2871,7 @@ function extractFrame(world, context) {
2432
2871
  const transform = row.get(GlobalTransform);
2433
2872
  lightProbes.push({
2434
2873
  identity: String(row.entity),
2874
+ worldId: context.worldId,
2435
2875
  position: [transform.world[12] ?? 0, transform.world[13] ?? 0, transform.world[14] ?? 0],
2436
2876
  radius: probe.radius,
2437
2877
  irradiance: new Float32Array(probe.irradiance),
@@ -2494,19 +2934,21 @@ function extractFrame(world, context) {
2494
2934
  directionalDirection[1] ?? 0,
2495
2935
  directionalDirection[2] ?? 0
2496
2936
  );
2497
- const sun = directional === void 0 || directionalLength <= 1e-6 ? [] : [
2937
+ const sunIntensity = directional?.intensity ?? 0;
2938
+ const sunColor = sunIntensity > 0 && directional !== void 0 ? [
2939
+ (directional.color[0] ?? 0) / sunIntensity,
2940
+ (directional.color[1] ?? 0) / sunIntensity,
2941
+ (directional.color[2] ?? 0) / sunIntensity
2942
+ ] : [0, 0, 0];
2943
+ const sun = directional === void 0 || directional.entity === void 0 || directionalLength <= 1e-6 ? [] : [
2498
2944
  {
2499
- entityKey: 0,
2945
+ entityKey: directional.entity,
2500
2946
  direction: [
2501
2947
  -(directionalDirection?.[0] ?? 0) / directionalLength,
2502
2948
  -(directionalDirection?.[1] ?? 0) / directionalLength,
2503
2949
  -(directionalDirection?.[2] ?? 0) / directionalLength
2504
2950
  ],
2505
- color: [
2506
- directional.color[0] ?? 0,
2507
- directional.color[1] ?? 0,
2508
- directional.color[2] ?? 0
2509
- ],
2951
+ color: sunColor,
2510
2952
  intensity: directional.intensity
2511
2953
  }
2512
2954
  ];
@@ -2563,7 +3005,9 @@ function extractFrame(world, context) {
2563
3005
  let frustumTotal = 0;
2564
3006
  const explicitlyHidden = /* @__PURE__ */ new Set();
2565
3007
  let dispatch = [];
3008
+ const shadowMembershipEntries = [];
2566
3009
  const materialSnapshotCache = /* @__PURE__ */ new Map();
3010
+ const instanceSnapshotCache = /* @__PURE__ */ new Map();
2567
3011
  const skinnedMaterialSnapshotCache = /* @__PURE__ */ new Map();
2568
3012
  const meshRendererQuery = context.renderables === "none" ? [] : world.query({
2569
3013
  read: [MeshRenderer],
@@ -2606,7 +3050,8 @@ function extractFrame(world, context) {
2606
3050
  }
2607
3051
  const hasTransform = row.has(Transform);
2608
3052
  const meshFilter = row.get(MeshFilter);
2609
- const hasInstances = row.has(Instances);
3053
+ const instancesData = row.get(Instances);
3054
+ const hasInstances = instancesData !== void 0;
2610
3055
  const skin = row.get(Skin);
2611
3056
  const morphWeightsView = worldInternal._getArrayView(row.entity, MorphWeights, "weights");
2612
3057
  const hasMeshFilter = meshFilter !== void 0;
@@ -2641,9 +3086,7 @@ function extractFrame(world, context) {
2641
3086
  () => "renderer-override"
2642
3087
  );
2643
3088
  let materialBindingDiagnostics = [];
2644
- let gpuDrivenSubmeshes = [];
2645
- let gpuDrivenIndexed = false;
2646
- let gpuDrivenGeometry;
3089
+ let gpuDrivenMesh;
2647
3090
  const fAssetHandleVal = fAssetHandle;
2648
3091
  if (fAssetHandleVal !== void 0 && fAssetHandleVal !== 0 && assets !== void 0 && assets !== null) {
2649
3092
  const meshHandle = toShared(fAssetHandleVal);
@@ -2651,19 +3094,7 @@ function extractFrame(world, context) {
2651
3094
  if (meshRes.ok && meshRes.value.kind === "mesh") {
2652
3095
  const meshAsset = meshRes.value;
2653
3096
  const guid = meshRes.value.guid ?? "<no-guid>";
2654
- gpuDrivenSubmeshes = meshAsset.submeshes;
2655
- gpuDrivenIndexed = meshAsset.indices !== void 0;
2656
- const layoutProjection = deriveVertexLayoutProjection(meshAsset.attributes);
2657
- gpuDrivenGeometry = {
2658
- identity: `${guid}:${layoutProjection.digest}`,
2659
- vertexInputs: layoutProjection.attributes.map((attribute) => ({
2660
- semantic: attribute.key,
2661
- location: attribute.shaderLocation,
2662
- format: attribute.format
2663
- })),
2664
- topology: meshAsset.submeshes[0]?.topology ?? "triangle-list",
2665
- indexed: gpuDrivenIndexed
2666
- };
3097
+ gpuDrivenMesh = meshAsset;
2667
3098
  if (!Array.isArray(meshAsset.materialSlots) && world.get(entity, GlyphText).ok) {
2668
3099
  ensureGlyphMeshMaterialSlots(world, meshHandle);
2669
3100
  }
@@ -2830,28 +3261,28 @@ function extractFrame(world, context) {
2830
3261
  } else {
2831
3262
  const resolvedResult = walkMaterialPassesOverSharedRefs(world, tagged, assets);
2832
3263
  if (!resolvedResult.ok) {
2833
- const err6 = resolvedResult.error;
2834
- switch (err6.code) {
3264
+ const err8 = resolvedResult.error;
3265
+ switch (err8.code) {
2835
3266
  case "material-parent-not-found":
2836
3267
  case "material-no-effective-pass":
2837
3268
  case "material-value-unknown":
2838
3269
  case "material-value-type-mismatch":
2839
3270
  case "material-contract-program-mismatch":
2840
- worldInternal._routeError(err6, {
3271
+ worldInternal._routeError(err8, {
2841
3272
  severity: Severity.Error,
2842
- systemName: `RenderSystem.extract (${err6.code})`
3273
+ systemName: `RenderSystem.extract (${err8.code})`
2843
3274
  });
2844
3275
  break;
2845
3276
  case "material-circular-inheritance":
2846
- worldInternal._routeError(err6, {
3277
+ worldInternal._routeError(err8, {
2847
3278
  severity: Severity.Error,
2848
3279
  systemName: "RenderSystem.extract (material-circular-inheritance)"
2849
3280
  });
2850
3281
  break;
2851
3282
  default:
2852
- worldInternal._routeError(err6, {
3283
+ worldInternal._routeError(err8, {
2853
3284
  severity: Severity.Error,
2854
- systemName: `RenderSystem.extract (_materialWalk: ${err6.code})`
3285
+ systemName: `RenderSystem.extract (_materialWalk: ${err8.code})`
2855
3286
  });
2856
3287
  }
2857
3288
  continue;
@@ -2867,6 +3298,11 @@ function extractFrame(world, context) {
2867
3298
  assets,
2868
3299
  materialContext
2869
3300
  );
3301
+ const materialSceneIndexProgramKeys = materialSceneIndexProgramKeysForMaterial(
3302
+ asset,
3303
+ assets,
3304
+ materialContext
3305
+ );
2870
3306
  const authoredFirstPassShader = runtimeMaterialShaderIdForMaterial(
2871
3307
  allPasses,
2872
3308
  void 0
@@ -2983,6 +3419,16 @@ function extractFrame(world, context) {
2983
3419
  firstPassShader,
2984
3420
  materialParamSchema.length > 0 ? derive(materialParamSchema).textureFieldNames : firstPassShader !== void 0 && assets !== null && assets !== void 0 ? assets.materialShaderTextureFieldNames(firstPassShader) : void 0
2985
3421
  ) ?? BUILTIN_USER_REGION_TEXTURE_FIELDS;
3422
+ const authoredTextureFields = collectAuthoredMaterialTextureFields(
3423
+ resolved.values,
3424
+ firstPassShader,
3425
+ materialParamSchema.length > 0 ? materialParamSchema : void 0,
3426
+ assets
3427
+ );
3428
+ const authoredSamplerFields = collectAuthoredMaterialSamplerFields(
3429
+ resolved.values,
3430
+ authoredTextureFields
3431
+ );
2986
3432
  const textureHandles = /* @__PURE__ */ new Map();
2987
3433
  const videoTextureFields = /* @__PURE__ */ new Map();
2988
3434
  for (const field of userRegionFields) {
@@ -3010,7 +3456,15 @@ function extractFrame(world, context) {
3010
3456
  pv.occlusionTexture
3011
3457
  );
3012
3458
  const textureCoordinates = collectMaterialTextureCoordinates(pv);
3013
- const textureSources = collectMaterialTextureSources(pv, world);
3459
+ const textureSources = collectMaterialTextureSources(
3460
+ pv,
3461
+ world,
3462
+ materialTextureSourceFields(
3463
+ materialParamSchema.length > 0 ? materialParamSchema : void 0
3464
+ ),
3465
+ materialTextureSourceStats,
3466
+ materialTextureSourceCache
3467
+ );
3014
3468
  const emissivePv = pv.emissive;
3015
3469
  const firstPassTransparent = allPasses[0]?.renderState?.blend !== void 0;
3016
3470
  if (isSprite) {
@@ -3064,12 +3518,20 @@ function extractFrame(world, context) {
3064
3518
  normalScale: normalScalePv,
3065
3519
  materialShaderId: firstPassShader,
3066
3520
  materialProgramKeys,
3521
+ materialSceneIndexProgramKeys,
3067
3522
  materialHandle: handleRaw,
3068
3523
  renderState: pipelineRenderState(allPasses[0]?.renderState),
3069
3524
  paramSnapshot: paramSnap,
3070
3525
  ...materialParamSchema.length > 0 && { materialParamSchema },
3526
+ standardTextureMask: materialStandardTextureMask(
3527
+ resolved.parameters,
3528
+ firstPassShader,
3529
+ pv
3530
+ ),
3071
3531
  ...textureCoordinates.size > 0 && { textureCoordinates },
3532
+ ...authoredTextureFields === void 0 ? {} : { authoredTextureFields },
3072
3533
  ...samplerHandles.size > 0 && { samplerHandles },
3534
+ ...authoredSamplerFields === void 0 ? {} : { authoredSamplerFields },
3073
3535
  ...textureHandles.size > 0 && { textureHandles },
3074
3536
  ...textureSources.size > 0 && { textureSources },
3075
3537
  ...videoTextureFields.size > 0 && { videoTextureFields },
@@ -3155,6 +3617,12 @@ function extractFrame(world, context) {
3155
3617
  }
3156
3618
  if (isRenderable) {
3157
3619
  let skinSlice;
3620
+ const skinIdentity = hasSkin ? skinPaletteIdentity(world, entity) : void 0;
3621
+ const releaseSkinIdentity = () => {
3622
+ if (skinIdentity !== void 0) {
3623
+ skinPaletteAllocator?.releasePersistentSlice(skinIdentity);
3624
+ }
3625
+ };
3158
3626
  if (hasSkin) {
3159
3627
  const skeletonHandleRaw = skinSkeletonView;
3160
3628
  if (skeletonHandleRaw !== void 0 && skeletonHandleRaw !== 0 && assets !== void 0 && assets !== null) {
@@ -3163,6 +3631,7 @@ function extractFrame(world, context) {
3163
3631
  severity: Severity.Error,
3164
3632
  systemName: "RenderSystem.extract (skin-instances-coexist)"
3165
3633
  });
3634
+ releaseSkinIdentity();
3166
3635
  continue;
3167
3636
  }
3168
3637
  const skeletonHandle = toShared(skeletonHandleRaw);
@@ -3172,11 +3641,15 @@ function extractFrame(world, context) {
3172
3641
  severity: Severity.Error,
3173
3642
  systemName: "RenderSystem.extract (skeleton-resolve-failed)"
3174
3643
  });
3644
+ releaseSkinIdentity();
3175
3645
  continue;
3176
3646
  }
3177
3647
  const skeleton = skeletonRes.value;
3178
3648
  const skinJoints = skin?.joints;
3179
- if (skinJoints === void 0) continue;
3649
+ if (skinJoints === void 0) {
3650
+ releaseSkinIdentity();
3651
+ continue;
3652
+ }
3180
3653
  const jointsLength = skinJoints.length;
3181
3654
  if (jointsLength !== skeleton.jointCount) {
3182
3655
  worldInternal._routeError(
@@ -3186,6 +3659,7 @@ function extractFrame(world, context) {
3186
3659
  systemName: "RenderSystem.extract (joint-count-mismatch)"
3187
3660
  }
3188
3661
  );
3662
+ releaseSkinIdentity();
3189
3663
  continue;
3190
3664
  }
3191
3665
  const jointWorlds = new Array(skeleton.jointCount);
@@ -3207,6 +3681,7 @@ function extractFrame(world, context) {
3207
3681
  severity: Severity.Error,
3208
3682
  systemName: "RenderSystem.extract (joint-entity-dangling)"
3209
3683
  });
3684
+ releaseSkinIdentity();
3210
3685
  continue;
3211
3686
  }
3212
3687
  const ibmFlat = skeleton.inverseBindMatrices;
@@ -3215,25 +3690,33 @@ function extractFrame(world, context) {
3215
3690
  ibms[jIdx] = ibmFlat.subarray(jIdx * 16, jIdx * 16 + 16);
3216
3691
  }
3217
3692
  if (skinPaletteAllocator !== null) {
3218
- const slice = typeof skinPaletteAllocator.allocateSliceFor === "function" ? skinPaletteAllocator.allocateSliceFor(
3219
- `${world.identity}:${entity}`,
3220
- skeleton.jointCount
3221
- ) : skinPaletteAllocator.allocateSlice(skeleton.jointCount);
3222
- skinPaletteAllocator.writeJointPalette(slice, ibms, jointWorlds);
3223
- skinSlice = {
3224
- jointCount: slice.jointCount,
3225
- byteOffset: slice.byteOffset,
3226
- buffer: slice.buffer
3227
- };
3693
+ const identity = skinPaletteIdentity(world, entity);
3694
+ const generation = skeletonHandleRaw >>> 0 ^ skeleton.jointCount;
3695
+ const bounds = hasFiniteOrderedLocalAabb(skeleton.bounds) ? new Float32Array(skeleton.bounds) : void 0;
3696
+ skinPaletteAllocator.observePersistentJoints(identity, ibms, jointWorlds);
3697
+ const receipt = skinPaletteAllocator.allocatePersistentSlice({
3698
+ identity,
3699
+ generation: generation >>> 0,
3700
+ jointCount: skeleton.jointCount,
3701
+ ...bounds === void 0 ? {} : { bounds }
3702
+ });
3703
+ skinPaletteAllocator.writePersistentJointPalette(receipt, ibms, jointWorlds);
3704
+ skinSlice = receipt;
3228
3705
  }
3229
3706
  }
3230
3707
  }
3231
- if (materialSnap.materialShaderId === "forgeax::pbr-skin" && skinSlice === void 0) {
3232
- pendingDispatch.length = 0;
3233
- continue;
3708
+ if (skinSlice === void 0 && hasSkin) {
3709
+ releaseSkinIdentity();
3710
+ if (materialSnap.materialShaderId === "forgeax::pbr-skin") {
3711
+ pendingDispatch.length = 0;
3712
+ continue;
3713
+ }
3234
3714
  }
3235
3715
  const worldView = worldInternal._getArrayView(entity, GlobalTransform, "world");
3236
- if (worldView === void 0) continue;
3716
+ if (worldView === void 0) {
3717
+ releaseSkinIdentity();
3718
+ continue;
3719
+ }
3237
3720
  const worldMat = new Float32Array(worldView);
3238
3721
  const transformSnap = { world: worldMat };
3239
3722
  const materialsArr = [materialSnap];
@@ -3252,7 +3735,9 @@ function extractFrame(world, context) {
3252
3735
  context.materialContext === void 0 ? void 0 : {
3253
3736
  ...context.materialContext,
3254
3737
  geometry: hasSkin ? "skinned" : context.materialContext.geometry
3255
- }
3738
+ },
3739
+ materialTextureSourceStats,
3740
+ materialTextureSourceCache
3256
3741
  )
3257
3742
  );
3258
3743
  }
@@ -3344,7 +3829,7 @@ function extractFrame(world, context) {
3344
3829
  lods = meshAsset.lods;
3345
3830
  lodHysteresis = meshAsset.lodHysteresis;
3346
3831
  morph = morphSnapshotFor(meshAsset, morphWeightsView);
3347
- const meshAabb = meshAsset.aabb;
3832
+ const meshAabb = skinSlice?.bounds ?? meshAsset.aabb;
3348
3833
  if (morph === void 0 && hasFiniteOrderedLocalAabb(meshAabb)) {
3349
3834
  localAabb = new Float32Array(meshAabb);
3350
3835
  }
@@ -3356,7 +3841,7 @@ function extractFrame(world, context) {
3356
3841
  })() : lines === void 0 ? void 0 : { kind: "lines", widthPx: lines.widthPx };
3357
3842
  const cullingLocalAabb = expandPointsLinesBounds(localAabb ?? [], pointsLinesStyle);
3358
3843
  const pointsLines = pointsLinesComponent === void 0 ? void 0 : {
3359
- worldId: 0,
3844
+ worldId: context.worldId,
3360
3845
  entityKey: entity,
3361
3846
  component: pointsLinesComponent,
3362
3847
  meshHandle: assetHandleRaw,
@@ -3373,27 +3858,44 @@ function extractFrame(world, context) {
3373
3858
  };
3374
3859
  let instancesSnap;
3375
3860
  if (hasInstances) {
3376
- const transforms = worldInternal._getArrayView(entity, Instances, "transforms") ?? new Float32Array();
3377
- if (transforms.length % 16 !== 0) {
3378
- worldInternal._routeError(
3379
- new InstanceTransformsStrideMismatchError(transforms.length),
3380
- {
3381
- severity: Severity.Error,
3382
- systemName: "RenderSystem.extract (Instances stride)"
3383
- }
3861
+ const collectionId = instancesData?.collectionId;
3862
+ let collectionResult = collectionId !== void 0 ? instanceSnapshotCache.get(collectionId) : void 0;
3863
+ if (collectionResult === void 0) {
3864
+ collectionResult = collectionId !== void 0 && collectionId > 0 && instanceCollections !== void 0 ? instanceCollections.snapshot(collectionId) : err(
3865
+ new InstanceCollectionError(
3866
+ "instance-collection-invalid",
3867
+ "Instances.collectionId references a live renderer-owned collection",
3868
+ "create the collection through renderer.instances before attaching Instances",
3869
+ {
3870
+ operation: "inspect",
3871
+ expected: "a positive collectionId with a live renderer owner",
3872
+ actual: Number(collectionId ?? 0),
3873
+ ...collectionId === void 0 ? {} : { collectionId }
3874
+ }
3875
+ )
3384
3876
  );
3877
+ if (collectionId !== void 0)
3878
+ instanceSnapshotCache.set(collectionId, collectionResult);
3879
+ }
3880
+ if (collectionResult === void 0) continue;
3881
+ if (!collectionResult.ok) {
3882
+ worldInternal._routeError(collectionResult.error, {
3883
+ severity: Severity.Error,
3884
+ systemName: "RenderSystem.extract (Instances collection)"
3885
+ });
3385
3886
  continue;
3386
3887
  }
3387
- const projected = instanceCollections?.project(world, entity, transforms);
3388
3888
  instancesSnap = {
3389
- transforms: projected?.transforms ?? new Float32Array(transforms),
3390
- instanceCount: transforms.length / 16,
3889
+ transforms: collectionResult.value.transforms,
3890
+ instanceCount: collectionResult.value.count,
3891
+ collectionId: collectionResult.value.collectionId,
3892
+ revision: collectionResult.value.revision,
3893
+ capacity: collectionResult.value.capacity,
3894
+ dirtyRanges: collectionResult.value.dirtyRanges,
3391
3895
  cacheKey: entity,
3392
- archVersion: projected === void 0 ? fingerprintNumericArray(transforms) : 0,
3393
- ...projected === void 0 ? {} : {
3394
- collectionId: projected.collectionId,
3395
- revision: projected.revision
3396
- }
3896
+ // Explicit collection revisions supersede ECS archetype content
3897
+ // hashes; retain zero as the legacy sprite-only field value.
3898
+ archVersion: 0
3397
3899
  };
3398
3900
  }
3399
3901
  const baseRenderable = {
@@ -3406,7 +3908,7 @@ function extractFrame(world, context) {
3406
3908
  materials: materialsArr,
3407
3909
  materialBindingSources,
3408
3910
  materialBindingDiagnostics,
3409
- worldId: 0,
3911
+ worldId: context.worldId,
3410
3912
  entityKey: entity,
3411
3913
  ...authorVisible ? {} : { authorVisible: false },
3412
3914
  ...skinSlice !== void 0 ? { skin: skinSlice } : {},
@@ -3417,32 +3919,25 @@ function extractFrame(world, context) {
3417
3919
  ...pointsLines !== void 0 ? { pointsLines } : {}
3418
3920
  };
3419
3921
  const gpuDrivenDraws = buildGpuDrivenDraws({
3420
- submeshes: gpuDrivenSubmeshes,
3421
- indexed: gpuDrivenIndexed,
3922
+ mesh: gpuDrivenMesh,
3422
3923
  materials: materialsArr,
3423
3924
  fallbackMaterial: materialSnap,
3424
- ...gpuDrivenGeometry === void 0 || getMaterialShaderArtifact === void 0 ? {} : {
3425
- prepare(draw, drawMaterial) {
3426
- const materialShaderId = drawMaterial.materialShaderId;
3427
- if (materialShaderId === void 0) return void 0;
3428
- const artifact = getMaterialShaderArtifact(materialShaderId);
3429
- if (artifact?.receipt === void 0) return void 0;
3430
- const geometry = {
3431
- ...gpuDrivenGeometry,
3432
- topology: draw.topology,
3433
- indexed: draw.kind === "indexed"
3434
- };
3435
- const result = resolvePreparedGpuDrivenDraw({
3436
- snapshot: { ...baseRenderable, material: drawMaterial },
3437
- artifact,
3438
- geometry,
3439
- generation: artifact.receipt.generation,
3440
- draw
3441
- });
3442
- return result.ok ? result.value : void 0;
3443
- }
3925
+ baseSnapshot: baseRenderable,
3926
+ ...getMaterialShaderArtifact === void 0 ? {} : { getMaterialShaderArtifact },
3927
+ ...lods === void 0 ? {} : {
3928
+ lodMeshes: lods.map((lod) => {
3929
+ const lower = assets?.lookup(lod.mesh);
3930
+ return lower?.kind === "mesh" ? lower : void 0;
3931
+ })
3444
3932
  }
3445
3933
  });
3934
+ for (const draw of gpuDrivenDraws) {
3935
+ if (draw.preparationError === void 0) continue;
3936
+ worldInternal._routeError(draw.preparationError, {
3937
+ severity: Severity.Error,
3938
+ systemName: `RenderSystem.extract (gpu-driven-preparation:${draw.preparationError.code})`
3939
+ });
3940
+ }
3446
3941
  const renderable = morph === void 0 && gpuDrivenDraws.length > 0 ? { ...baseRenderable, gpuDrivenDraws } : baseRenderable;
3447
3942
  if (localAabb !== void 0) {
3448
3943
  const derivedInstancesBounds = instancesSnap === void 0 || instancesSnap.instanceCount === 0 ? void 0 : deriveInstancesUnionBounds({
@@ -3477,16 +3972,96 @@ function extractFrame(world, context) {
3477
3972
  }
3478
3973
  if (!visible) {
3479
3974
  frustumCulled += 1;
3975
+ const shadowVisible = shadowFrusta.length > 0 && pendingDispatch.some((entry) => entry.tags.LightMode === "ShadowCaster") && shadowFrusta.some(
3976
+ (lightPlanes) => frustum.intersectsBox(lightPlanes, worldAabb)
3977
+ );
3978
+ if (!shadowVisible) continue;
3979
+ for (let i = pendingDispatch.length - 1; i >= 0; i -= 1) {
3980
+ if (pendingDispatch[i]?.tags.LightMode !== "ShadowCaster") {
3981
+ pendingDispatch.splice(i, 1);
3982
+ }
3983
+ }
3984
+ }
3985
+ }
3986
+ }
3987
+ const localShadowMembershipEntries = [];
3988
+ if (gpuDrivenMesh !== void 0) {
3989
+ const worldEntity = worldEntityKey(context.worldId, entity);
3990
+ for (const [drawItemIndex, submesh] of gpuDrivenMesh.submeshes.entries()) {
3991
+ if (submesh.topology !== "triangle-list" && submesh.topology !== "triangle-strip") {
3480
3992
  continue;
3481
3993
  }
3994
+ const material = materialsArr[submesh.materialSlot] ?? materialSnap;
3995
+ const materialHandle = material.materialHandle ?? -1;
3996
+ const shadowEntries = pendingDispatch.filter(
3997
+ (entry) => entry.tags.LightMode === "ShadowCaster" && entry.materialHandle === materialHandle
3998
+ );
3999
+ const draw = renderable.gpuDrivenDraws?.find(
4000
+ (candidate, compactIndex) => gpuDrivenSourceDrawItemIndex(candidate, compactIndex) === drawItemIndex
4001
+ );
4002
+ const cpuReason = shadowCasterCpuReason(
4003
+ material,
4004
+ draw,
4005
+ shadowEntries,
4006
+ morph,
4007
+ skinSlice
4008
+ );
4009
+ for (const entry of shadowEntries) {
4010
+ const membership = {
4011
+ worldEntity,
4012
+ renderableIndex: renderables.length,
4013
+ drawItemIndex,
4014
+ materialHandle,
4015
+ passIndex: entry.passIndex,
4016
+ ...entry.materialShaderId === void 0 ? {} : { materialShaderId: entry.materialShaderId },
4017
+ ...entry.vertexEntry === void 0 ? {} : { vertexEntry: entry.vertexEntry },
4018
+ ...entry.fragmentEntry === void 0 ? {} : { fragmentEntry: entry.fragmentEntry },
4019
+ ...entry.renderState === void 0 ? {} : { renderState: entry.renderState },
4020
+ ...cpuReason === void 0 ? {} : { cpuReason },
4021
+ gpuDrivenEligible: cpuReason === void 0
4022
+ };
4023
+ shadowMembershipEntries.push(membership);
4024
+ localShadowMembershipEntries.push(membership);
4025
+ }
3482
4026
  }
3483
4027
  }
4028
+ const shadowCasterPasses = localShadowMembershipEntries.map((membership) => ({
4029
+ drawItemIndex: membership.drawItemIndex,
4030
+ materialHandle: membership.materialHandle,
4031
+ passIndex: membership.passIndex,
4032
+ ...membership.materialShaderId === void 0 ? {} : { materialShaderId: membership.materialShaderId },
4033
+ ...membership.renderState === void 0 ? {} : { renderState: membership.renderState },
4034
+ ...membership.cpuReason === void 0 ? {} : { cpuReason: membership.cpuReason }
4035
+ }));
4036
+ const renderableWithShadowPasses = shadowCasterPasses.length === 0 ? renderable : { ...renderable, shadowCasterPasses };
3484
4037
  flushPendingDispatch(pendingDispatch);
3485
- renderables.push(renderable);
4038
+ renderables.push(renderableWithShadowPasses);
3486
4039
  }
3487
4040
  }
3488
4041
  }
3489
4042
  dispatch = sortDispatchByQueue(dispatch);
4043
+ const shadowCasterEntityKeys = /* @__PURE__ */ new Set();
4044
+ const shadowCasterDrawKeys = /* @__PURE__ */ new Set();
4045
+ const shadowCasterMembership = /* @__PURE__ */ new Map();
4046
+ for (const entry of dispatch) {
4047
+ if (entry.tags.LightMode !== "ShadowCaster") continue;
4048
+ const renderable = renderables[entry.renderableIndex];
4049
+ if (renderable !== void 0) {
4050
+ const worldEntity = worldEntityKey(renderable.worldId, renderable.entityKey);
4051
+ shadowCasterEntityKeys.add(worldEntity);
4052
+ }
4053
+ }
4054
+ for (const membership of shadowMembershipEntries) {
4055
+ const key = gpuDrivenShadowDrawKey(
4056
+ membership.worldEntity,
4057
+ membership.materialHandle,
4058
+ membership.drawItemIndex,
4059
+ membership.passIndex
4060
+ );
4061
+ shadowCasterDrawKeys.add(key);
4062
+ shadowCasterMembership.set(key, membership);
4063
+ shadowCasterEntityKeys.add(membership.worldEntity);
4064
+ }
3490
4065
  const postProcessParams = /* @__PURE__ */ new Map();
3491
4066
  const postProcessParamsQuery = world.query({ with: [PostProcessParams] }).unwrap();
3492
4067
  for (const row of postProcessParamsQuery) {
@@ -3510,6 +4085,9 @@ function extractFrame(world, context) {
3510
4085
  ...volumetricFog === void 0 ? {} : { volumetricFog },
3511
4086
  renderables,
3512
4087
  dispatch,
4088
+ shadowCasterEntityKeys,
4089
+ shadowCasterDrawKeys,
4090
+ ...shadowCasterMembership.size === 0 ? {} : { shadowCasterMembership: [...shadowCasterMembership.values()] },
3513
4091
  skylight,
3514
4092
  skylightCount,
3515
4093
  lightProbes,
@@ -3519,19 +4097,21 @@ function extractFrame(world, context) {
3519
4097
  ...fogFailure === void 0 ? {} : { fogFailure },
3520
4098
  frustumStats: { culled: frustumCulled, total: frustumTotal },
3521
4099
  visibilityStats: { explicitlyHidden: explicitlyHidden.size },
4100
+ materialTextureSources: materialTextureSourceStats,
3522
4101
  postProcessParams,
3523
4102
  visibilitySnapshots: [context.visibility],
3524
4103
  featureVisibilitySnapshots: [{ world, snapshot: context.visibility }],
3525
4104
  hiddenEntityReports: [...explicitlyHidden].map((entity) => ({ world, entity }))
3526
4105
  };
3527
4106
  }
4107
+ var DEFAULT_MATERIAL_SNAPSHOT = Object.freeze({
4108
+ baseColor: vec3.create(0.5, 0.5, 0.5),
4109
+ metallic: 0,
4110
+ roughness: 1,
4111
+ materialHandle: 0
4112
+ });
3528
4113
  function defaultMaterialSnapshot(materialHandle = 0) {
3529
- return {
3530
- baseColor: vec3.create(0.5, 0.5, 0.5),
3531
- metallic: 0,
3532
- roughness: 1,
3533
- materialHandle
3534
- };
4114
+ return materialHandle === 0 ? DEFAULT_MATERIAL_SNAPSHOT : { ...DEFAULT_MATERIAL_SNAPSHOT, materialHandle };
3535
4115
  }
3536
4116
  function identityProjection() {
3537
4117
  const projection = new Float32Array(16);
@@ -3685,6 +4265,31 @@ function materialTextureFields(shaderId, fields) {
3685
4265
  }
3686
4266
  return fields;
3687
4267
  }
4268
+ function declaredMaterialTextureFields(shaderId, paramSchema, assets) {
4269
+ return materialTextureFields(
4270
+ shaderId,
4271
+ paramSchema !== void 0 ? derive(paramSchema).textureFieldNames : shaderId !== void 0 ? assets.materialShaderTextureFieldNames(shaderId) : void 0
4272
+ );
4273
+ }
4274
+ function collectAuthoredMaterialTextureFields(values, shaderId, paramSchema, assets) {
4275
+ const fields = declaredMaterialTextureFields(shaderId, paramSchema, assets);
4276
+ if (fields === void 0) return void 0;
4277
+ const authored = /* @__PURE__ */ new Set();
4278
+ for (const field of fields) {
4279
+ if (Object.hasOwn(values, field)) authored.add(field);
4280
+ }
4281
+ return authored.size === 0 ? void 0 : authored;
4282
+ }
4283
+ function collectAuthoredMaterialSamplerFields(values, textureFields) {
4284
+ const authored = /* @__PURE__ */ new Set();
4285
+ for (const field of textureFields ?? []) {
4286
+ if (materialTextureValue(values[field])?.sampler !== void 0) authored.add(field);
4287
+ }
4288
+ if (Object.hasOwn(values, "sampler") && values.sampler !== void 0) {
4289
+ authored.add("baseColorTexture");
4290
+ }
4291
+ return authored.size === 0 ? void 0 : authored;
4292
+ }
3688
4293
  function runtimeMaterialShaderId(module, passName) {
3689
4294
  if (passName === "shadow-caster" && (module === "forgeax_material::standard" || module === "forgeax_material::unlit" || module === "forgeax::default-standard-pbr" || module === "forgeax::default-unlit")) {
3690
4295
  return "forgeax::default-shadow-caster";
@@ -3703,26 +4308,62 @@ function runtimeMaterialShaderId(module, passName) {
3703
4308
  }
3704
4309
  }
3705
4310
  function materialProgramKeysForMaterial(material, assets, context) {
4311
+ return materialProgramKeysForAddress(material, assets, context, "direct");
4312
+ }
4313
+ function materialSceneIndexProgramKeysForMaterial(material, assets, context) {
3706
4314
  const projection = assets.getMaterialProjectionForPayload(material);
3707
4315
  if (projection === void 0) return void 0;
3708
4316
  if (context === void 0)
3709
4317
  throw new Error("Published material selection requires renderer-owned compiler context");
3710
- return Object.fromEntries(
3711
- projection.passes.map((pass) => {
3712
- const mode = String(
3713
- pass.renderState?.tags?.LightMode ?? pass.name
3714
- );
3715
- const selectedContext = {
3716
- ...context,
3717
- pass: /shadow/i.test(mode) ? "shadow" : /depth/i.test(mode) ? "depth" : "forward",
3718
- pipeline: /deferred|gbuffer/i.test(mode) ? "deferred" : context.pipeline
3719
- };
3720
- return [
4318
+ const entries = {};
4319
+ for (const pass of projection.passes) {
4320
+ const mode = String(
4321
+ pass.renderState?.tags?.LightMode ?? pass.name
4322
+ );
4323
+ const passKind = /shadow/i.test(mode) ? "shadow" : /depth/i.test(mode) ? "depth" : "forward";
4324
+ const selectedContext = {
4325
+ ...context,
4326
+ pass: passKind,
4327
+ pipeline: /deferred|gbuffer/i.test(mode) ? "deferred" : context.pipeline
4328
+ };
4329
+ try {
4330
+ const selected = selectMaterialPassProgram(
4331
+ projection,
3721
4332
  pass.name,
3722
- selectMaterialPassProgram(projection, pass.name, selectedContext).specializationKey
3723
- ];
3724
- })
3725
- );
4333
+ selectedContext,
4334
+ "scene-index"
4335
+ );
4336
+ entries[pass.name] = { specializationKey: selected.specializationKey, pass: passKind };
4337
+ } catch (error) {
4338
+ if (!isMissingMaterialProgram(error)) throw error;
4339
+ }
4340
+ }
4341
+ return Object.keys(entries).length === 0 ? void 0 : entries;
4342
+ }
4343
+ function isMissingMaterialProgram(error) {
4344
+ return error !== null && typeof error === "object" && error.code === "material-specialization-not-cooked";
4345
+ }
4346
+ function materialProgramKeysForAddress(material, assets, context, address) {
4347
+ const projection = assets.getMaterialProjectionForPayload(material);
4348
+ if (projection === void 0) return void 0;
4349
+ if (context === void 0)
4350
+ throw new Error("Published material selection requires renderer-owned compiler context");
4351
+ const entries = [];
4352
+ for (const pass of projection.passes) {
4353
+ const mode = String(
4354
+ pass.renderState?.tags?.LightMode ?? pass.name
4355
+ );
4356
+ const selectedContext = {
4357
+ ...context,
4358
+ pass: /shadow/i.test(mode) ? "shadow" : /depth/i.test(mode) ? "depth" : "forward",
4359
+ pipeline: /deferred|gbuffer/i.test(mode) ? "deferred" : context.pipeline
4360
+ };
4361
+ entries.push([
4362
+ pass.name,
4363
+ selectMaterialPassProgram(projection, pass.name, selectedContext, address).specializationKey
4364
+ ]);
4365
+ }
4366
+ return entries.length === 0 ? void 0 : Object.fromEntries(entries);
3726
4367
  }
3727
4368
  function runtimeMaterialShaderIdForMaterial(passes, programs) {
3728
4369
  const pass = passes.find(
@@ -3763,6 +4404,36 @@ function pipelineRenderState(renderState) {
3763
4404
  ...frontFace !== void 0 && { frontFace }
3764
4405
  };
3765
4406
  }
4407
+ function shadowCasterCpuReason(material, draw, shadowEntries, morph, skin) {
4408
+ if (shadowEntries.length !== 1) return "multi-pass";
4409
+ if (material.transparent === true || material.renderState?.blend !== void 0) {
4410
+ return "transparent";
4411
+ }
4412
+ if (morph !== void 0) return "morph";
4413
+ const shadowEntry = shadowEntries[0];
4414
+ if (shadowEntry?.renderState !== void 0) return "unsupported-render-state";
4415
+ if (draw === void 0) return "missing-gpu-draw";
4416
+ if (draw.prepared === void 0) return "unprepared";
4417
+ const preparedMaterial = draw.prepared.identity.material;
4418
+ const preparedDeformation = draw.prepared.identity.deformation;
4419
+ const materialContractMatches = preparedMaterial === material.materialShaderId;
4420
+ const deformationContractMatches = skin === void 0 && preparedDeformation === "rigid" || skin !== void 0 && preparedDeformation === "skin";
4421
+ if (!materialContractMatches || !deformationContractMatches) return "prepared-contract";
4422
+ if (preparedDeformation === "skin" && !hasFiniteOrderedSkinBounds(skin?.bounds)) {
4423
+ return "missing-skin-bounds";
4424
+ }
4425
+ return void 0;
4426
+ }
4427
+ function hasFiniteOrderedSkinBounds(bounds) {
4428
+ if (bounds === void 0 || bounds.length !== 6) return false;
4429
+ const minX = bounds[0];
4430
+ const minY = bounds[1];
4431
+ const minZ = bounds[2];
4432
+ const maxX = bounds[3];
4433
+ const maxY = bounds[4];
4434
+ const maxZ = bounds[5];
4435
+ return minX !== void 0 && minY !== void 0 && minZ !== void 0 && maxX !== void 0 && maxY !== void 0 && maxZ !== void 0 && Number.isFinite(minX) && Number.isFinite(minY) && Number.isFinite(minZ) && Number.isFinite(maxX) && Number.isFinite(maxY) && Number.isFinite(maxZ) && minX <= maxX && minY <= maxY && minZ <= maxZ;
4436
+ }
3766
4437
  var guidHandleInternByWorld = /* @__PURE__ */ new WeakMap();
3767
4438
  function internSharedRefFromGuid(world, assetsRef, guid, brand) {
3768
4439
  let perWorld = guidHandleInternByWorld.get(world);
@@ -3787,8 +4458,8 @@ function internSharedRefFromGuid(world, assetsRef, guid, brand) {
3787
4458
  return handle;
3788
4459
  }
3789
4460
  function resolveVideoFieldHandle(value, world, assetsRef) {
3790
- const texture = materialTextureValue(value);
3791
- const textureGuid = assetReferenceText(texture?.texture ?? value);
4461
+ const texture2 = materialTextureValue(value);
4462
+ const textureGuid = assetReferenceText(texture2?.texture ?? value);
3792
4463
  if (textureGuid === void 0) return void 0;
3793
4464
  const payload = assetsRef.lookup(textureGuid);
3794
4465
  if (payload === void 0 || payload.kind !== "video") return void 0;
@@ -3827,14 +4498,45 @@ function collectMaterialTextureCoordinates(values) {
3827
4498
  }
3828
4499
  return out;
3829
4500
  }
3830
- function collectMaterialTextureSources(values, world) {
4501
+ function materialTextureSourceFields(schema) {
4502
+ if (schema === void 0) return void 0;
4503
+ const fields = /* @__PURE__ */ new Set();
4504
+ for (const entry of schema) {
4505
+ if (entry.type.startsWith("texture")) fields.add(entry.name);
4506
+ }
4507
+ return fields;
4508
+ }
4509
+ function collectMaterialTextureSources(values, world, textureFields, stats, cache) {
3831
4510
  const out = /* @__PURE__ */ new Map();
3832
4511
  for (const [field, value] of Object.entries(values)) {
3833
- const reference = materialTextureRef(value);
4512
+ const structured = materialTextureValue(value);
4513
+ const schemaKnown = textureFields !== void 0;
4514
+ const schemaAdmitted = textureFields?.has(field) === true;
4515
+ if (schemaKnown && !schemaAdmitted) continue;
4516
+ const reference = structured?.texture ?? value;
4517
+ if (stats !== void 0) stats.sourceFieldsVisited += 1;
3834
4518
  if (typeof reference !== "number") continue;
3835
- const resolved = world.sharedRefs.resolve(toShared(reference));
3836
- if (!resolved.ok || resolveRenderTargetMaterialSource(resolved.value) === void 0) continue;
3837
- out.set(field, resolved.value);
4519
+ if (stats !== void 0) stats.numericSharedRefProbes += 1;
4520
+ let source;
4521
+ if (cache?.has(reference) === true) {
4522
+ if (stats !== void 0) stats.sourceCacheHits += 1;
4523
+ source = cache.get(reference) ?? void 0;
4524
+ } else {
4525
+ if (stats !== void 0) stats.sourceCacheMisses += 1;
4526
+ const resolved = world.sharedRefs.resolve(toShared(reference));
4527
+ if (!resolved.ok) {
4528
+ cache?.set(reference, null);
4529
+ } else {
4530
+ const binding = resolveRenderTargetMaterialSource(resolved.value);
4531
+ cache?.set(reference, binding === void 0 ? null : resolved.value);
4532
+ source = binding === void 0 ? void 0 : resolved.value;
4533
+ }
4534
+ }
4535
+ if (source === void 0) continue;
4536
+ if (stats !== void 0) {
4537
+ stats.producerRoutes.renderTarget = (stats.producerRoutes.renderTarget ?? 0) + 1;
4538
+ }
4539
+ out.set(field, source);
3838
4540
  }
3839
4541
  return out;
3840
4542
  }
@@ -3871,6 +4573,17 @@ var ENGINE_INJECTED_TEXTURE_FIELDS = /* @__PURE__ */ new Set(["emissiveTexture",
3871
4573
  function isEngineInjectedTextureField(shaderId, fieldName) {
3872
4574
  return isStandardPbrMaterialShader(shaderId) && ENGINE_INJECTED_TEXTURE_FIELDS.has(fieldName);
3873
4575
  }
4576
+ function materialStandardTextureMask(parameters, shaderId, values) {
4577
+ return isCanonicalStandardPbrMaterialShader(shaderId) ? standardTextureMask(
4578
+ // Canonical materials may provide values without redeclaring the root
4579
+ // schema. Pruning must agree with the texture binder in that route too.
4580
+ DEFAULT_STANDARD_PBR_PARAM_SCHEMA.filter(
4581
+ (entry) => entry.type === "texture2d" && (values[entry.name] !== void 0 || parameters?.some(
4582
+ (parameter) => parameter.name === entry.name && parameter.default !== void 0
4583
+ ))
4584
+ )
4585
+ ) : void 0;
4586
+ }
3874
4587
  function materialParametersToParamSchema(parameters, shaderId) {
3875
4588
  if (isCanonicalStandardPbrMaterialShader(shaderId)) return STANDARD_PIPELINE_PARAM_SCHEMA;
3876
4589
  return materialParametersToParamSchema$1(parameters);
@@ -3950,7 +4663,7 @@ function storeMaterialSnapshot(cache, handleRaw, snapshot, passes, root, assets)
3950
4663
  cache.set(handleRaw, entry);
3951
4664
  return entry;
3952
4665
  }
3953
- function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCache, persistentMaterialSnapshotCache, materialContext) {
4666
+ function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCache, persistentMaterialSnapshotCache, materialContext, materialTextureSourceStats, materialTextureSourceCache) {
3954
4667
  if (handleRaw === 0) return defaultMaterialSnapshot(handleRaw);
3955
4668
  const cached = materialSnapshotCache?.get(handleRaw);
3956
4669
  if (cached !== void 0) return cached.snapshot;
@@ -3982,6 +4695,11 @@ function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCa
3982
4695
  const resolved = resolvedResult.value;
3983
4696
  const allPasses = resolved.passes;
3984
4697
  const materialProgramKeys = materialProgramKeysForMaterial(asset, assetsRef, materialContext);
4698
+ const materialSceneIndexProgramKeys = materialSceneIndexProgramKeysForMaterial(
4699
+ asset,
4700
+ assetsRef,
4701
+ materialContext
4702
+ );
3985
4703
  const authoredFirstPassShader = runtimeMaterialShaderIdForMaterial(allPasses, void 0);
3986
4704
  const firstPassShader = runtimeMaterialShaderIdForMaterial(allPasses, materialProgramKeys);
3987
4705
  const pv = materialValuesToLinearRuntime(
@@ -4033,7 +4751,13 @@ function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCa
4033
4751
  pv,
4034
4752
  (value) => resolveTexLike(materialTextureRef(value), "SamplerAsset")
4035
4753
  );
4036
- const textureSources = collectMaterialTextureSources(pv, world);
4754
+ const textureSources = collectMaterialTextureSources(
4755
+ pv,
4756
+ world,
4757
+ materialTextureSourceFields(materialParamSchema.length > 0 ? materialParamSchema : void 0),
4758
+ materialTextureSourceStats,
4759
+ materialTextureSourceCache
4760
+ );
4037
4761
  const emissiveTextureHandle = resolveTexLike(
4038
4762
  materialTextureRef(pv.emissiveTexture),
4039
4763
  "TextureAsset"
@@ -4061,10 +4785,12 @@ function resolveMaterialSnapshot(handleRaw, world, assetsRef, materialSnapshotCa
4061
4785
  normalScale: normalScalePv,
4062
4786
  materialShaderId: firstPassShader,
4063
4787
  materialProgramKeys,
4788
+ materialSceneIndexProgramKeys,
4064
4789
  materialHandle: handleRaw,
4065
4790
  renderState: pipelineRenderState(allPasses[0]?.renderState),
4066
4791
  paramSnapshot: paramSnap,
4067
4792
  ...materialParamSchema.length > 0 && { materialParamSchema },
4793
+ standardTextureMask: materialStandardTextureMask(resolved.parameters, firstPassShader, pv),
4068
4794
  ...textureCoordinates.size > 0 && { textureCoordinates },
4069
4795
  ...textureHandles.size > 0 && { textureHandles },
4070
4796
  ...textureSources.size > 0 && { textureSources },
@@ -4156,43 +4882,11 @@ function pssmSplit(nearPlane, farPlane, cascadeCount, splitLambda) {
4156
4882
  }
4157
4883
  return result;
4158
4884
  }
4159
- var POINT_SHADOW_FACE_LOOK = [
4160
- vec3.create(1, 0, 0),
4161
- vec3.create(-1, 0, 0),
4162
- vec3.create(0, 1, 0),
4163
- vec3.create(0, -1, 0),
4164
- vec3.create(0, 0, 1),
4165
- vec3.create(0, 0, -1)
4166
- ];
4167
- var POINT_SHADOW_FACE_UP = [
4168
- vec3.create(0, -1, 0),
4169
- vec3.create(0, -1, 0),
4170
- vec3.create(0, 0, 1),
4171
- vec3.create(0, 0, -1),
4172
- vec3.create(0, -1, 0),
4173
- vec3.create(0, -1, 0)
4174
- ];
4175
4885
  function buildPointShadowMatrices(lightPos, near, far) {
4176
- const fovY = Math.PI / 2;
4177
- const aspect = 1;
4178
- const proj = mat4.create();
4179
- mat4.perspective(proj, fovY, aspect, near, far);
4180
- const out = [];
4181
- for (let i = 0; i < 6; i++) {
4182
- const look = POINT_SHADOW_FACE_LOOK[i];
4183
- const up = POINT_SHADOW_FACE_UP[i];
4184
- const target = vec3.create(
4185
- (lightPos[0] ?? 0) + (look[0] ?? 0),
4186
- (lightPos[1] ?? 0) + (look[1] ?? 0),
4187
- (lightPos[2] ?? 0) + (look[2] ?? 0)
4188
- );
4189
- const view = mat4.create();
4190
- mat4.lookAt(view, lightPos, target, up);
4191
- const vp = mat4.create();
4192
- mat4.multiply(vp, proj, view);
4193
- out.push(vp);
4194
- }
4195
- return out;
4886
+ return buildCubeCameraFaceViews({ position: lightPos, near, far }).map(({ viewProjection }) => {
4887
+ for (const offset of [0, 4, 8, 12]) viewProjection[offset] = -(viewProjection[offset] ?? 0);
4888
+ return viewProjection;
4889
+ });
4196
4890
  }
4197
4891
  function computeDirectionalCsm(direction, config, cameraData) {
4198
4892
  const cascadeCount = Math.round(config.cascadeCount);
@@ -4243,7 +4937,8 @@ function computeDirectionalCsm(direction, config, cameraData) {
4243
4937
  resultLightViewProjs.push(new Float32Array(16));
4244
4938
  continue;
4245
4939
  }
4246
- const cascadeNear = cIdx === 0 ? sNear : splits[cIdx - 1] ?? sFar;
4940
+ const previousSplit = splits[cIdx - 1] ?? sNear;
4941
+ const cascadeNear = cIdx === 0 ? sNear : Math.max(sNear, previousSplit * (1 - config.cascadeBlend));
4247
4942
  const cascadeFar = splits[cIdx] ?? sFar;
4248
4943
  const corners = computeFrustumCorners(
4249
4944
  cameraVP,
@@ -4280,7 +4975,7 @@ function computeDirectionalCsm(direction, config, cameraData) {
4280
4975
  minY,
4281
4976
  maxY,
4282
4977
  minZ,
4283
- maxZ
4978
+ maxZ: nearZ
4284
4979
  });
4285
4980
  resultLightViewProjs.push(new Float32Array(mat4.multiply(mat4.create(), orthoProj, lightView)));
4286
4981
  }
@@ -4311,15 +5006,32 @@ var ALL_VISIBLE = {
4311
5006
  function collectCameraSnapshots(world) {
4312
5007
  const worldInternal = createWorldInternalView(world);
4313
5008
  const cameras = [];
4314
- const cameraQuery = world.query({ read: [Camera], optional: [MotionBlur], with: [Transform, GlobalTransform] }).unwrap();
5009
+ const cameraQuery = world.query({
5010
+ read: [Camera],
5011
+ optional: [MotionBlur, DynamicResolution, ScreenSpaceReflection],
5012
+ with: [Transform, GlobalTransform]
5013
+ }).unwrap();
4315
5014
  for (const row of cameraQuery) {
4316
5015
  const cam = row.get(Camera);
4317
5016
  const motionBlur = row.get(MotionBlur);
5017
+ const dynamicResolution = row.get(DynamicResolution);
5018
+ const screenSpaceReflection = row.get(ScreenSpaceReflection);
4318
5019
  const entity = row.entity;
4319
5020
  const view = worldInternal._getArrayView(entity, GlobalTransform, "world");
4320
5021
  if (view === void 0) continue;
4321
5022
  const worldMat = new Float32Array(view);
4322
5023
  const target = resolveCameraTarget(world, cam.target);
5024
+ const hasNonDefaultOutput = cam.exposureMode !== CAMERA_EXPOSURE_MODE_MANUAL || cam.exposure !== 1 || cam.temperature !== 6504 || cam.tint !== 0 || cam.colorLut !== 0 || cam.colorLutStrength !== 0;
5025
+ const output = hasNonDefaultOutput ? {
5026
+ exposure: cameraExposureFromColumns(cam),
5027
+ temperature: cam.temperature,
5028
+ tint: cam.tint,
5029
+ colorLut: cam.colorLut,
5030
+ colorLutStrength: cam.colorLutStrength
5031
+ } : void 0;
5032
+ const antialias = antialiasFromF32(cam.antialias);
5033
+ const dynamicResolutionResult = validateDynamicResolutionCamera(dynamicResolution, antialias);
5034
+ if (!dynamicResolutionResult.ok) throw dynamicResolutionResult.error;
4323
5035
  cameras.push({
4324
5036
  entityKey: entity,
4325
5037
  ...target === void 0 ? {} : { target },
@@ -4338,7 +5050,9 @@ function collectCameraSnapshots(world) {
4338
5050
  tonemap: tonemapFromF32(cam.tonemap),
4339
5051
  exposure: cam.exposure,
4340
5052
  whitePoint: cam.whitePoint,
4341
- antialias: antialiasFromF32(cam.antialias),
5053
+ ...output === void 0 ? {} : { output },
5054
+ antialias,
5055
+ ...dynamicResolutionResult.value === void 0 ? {} : { dynamicResolution: dynamicResolutionResult.value },
4342
5056
  bloom: bloomEnabledFromF32(cam.bloom),
4343
5057
  bloomThreshold: cam.bloomThreshold,
4344
5058
  bloomIntensity: cam.bloomIntensity,
@@ -4355,6 +5069,13 @@ function collectCameraSnapshots(world) {
4355
5069
  maxRadiusPixels: motionBlur.maxRadiusPixels,
4356
5070
  sampleCount: motionBlur.sampleCount
4357
5071
  }
5072
+ },
5073
+ ...screenSpaceReflection === void 0 ? {} : {
5074
+ screenSpaceReflection: {
5075
+ maxDistance: screenSpaceReflection.maxDistance,
5076
+ thickness: screenSpaceReflection.thickness,
5077
+ maxRoughness: screenSpaceReflection.maxRoughness
5078
+ }
4358
5079
  }
4359
5080
  });
4360
5081
  }
@@ -4405,6 +5126,7 @@ function collectReflectionProbeFacts(world) {
4405
5126
  priority: probe.priority,
4406
5127
  intensity: probe.intensity,
4407
5128
  resolution: probe.resolution,
5129
+ boxProjection: probe.boxProjection,
4408
5130
  revision: probe.invalidationVersion,
4409
5131
  updateIntent: reflectionProbeUpdateIntentFromF32(probe.updateIntent),
4410
5132
  invalidationVersion: probe.invalidationVersion
@@ -4412,14 +5134,15 @@ function collectReflectionProbeFacts(world) {
4412
5134
  }
4413
5135
  return facts;
4414
5136
  }
4415
- function selectCameraRoles(world) {
5137
+ function selectCameraRoles(world, requestedEntityKey) {
4416
5138
  const cameras = collectCameraSnapshots(world);
4417
5139
  const displayEntities = cameras.filter((camera) => camera.target === void 0).map((camera) => camera.entityKey ?? 0);
5140
+ const hasExplicitSelection = requestedEntityKey !== void 0;
4418
5141
  const activeCameraIndex = selectActiveCameraIndex(
4419
5142
  displayEntities,
4420
- getActiveCamera(world)?.entity
5143
+ hasExplicitSelection ? requestedEntityKey : getActiveCamera(world)?.entity
4421
5144
  );
4422
- const displayEntityKey = displayEntities[activeCameraIndex] ?? displayEntities[0];
5145
+ const displayEntityKey = hasExplicitSelection ? displayEntities[activeCameraIndex] : displayEntities[activeCameraIndex] ?? displayEntities[0];
4423
5146
  const display = displayEntityKey === void 0 ? [] : cameras.filter((camera) => camera.entityKey === displayEntityKey);
4424
5147
  const candidates = cameras.map((camera) => ({
4425
5148
  worldId: 0,
@@ -4456,7 +5179,9 @@ function prepareExtractContext(world, options = {}) {
4456
5179
  resourceOwnerFog: options.resourceOwnerFog,
4457
5180
  cull: options.cull ?? "self",
4458
5181
  cullCameras: options.cullCameras,
5182
+ ...options.cameraEntityKey === void 0 ? {} : { cameraEntityKey: options.cameraEntityKey },
4459
5183
  renderables,
5184
+ worldId: options.worldId ?? 0,
4460
5185
  renderableEntities: options.renderableEntities,
4461
5186
  retainHidden: options.retainHidden ?? false,
4462
5187
  visibility: renderables === "none" ? ALL_VISIBLE : resolveVisibility(world),
@@ -4514,9 +5239,9 @@ function selectFogFrame(world) {
4514
5239
  if (state.lkg !== void 0) return state.lkg;
4515
5240
  throw fogSelection.error;
4516
5241
  }
4517
- function textureDigest(texture) {
5242
+ function textureDigest(texture2) {
4518
5243
  let hash = 2166136261;
4519
- for (const byte of texture.data) hash = Math.imul(hash ^ byte, 16777619) >>> 0;
5244
+ for (const byte of texture2.data) hash = Math.imul(hash ^ byte, 16777619) >>> 0;
4520
5245
  return `fnv1a:${hash.toString(16).padStart(8, "0")}`;
4521
5246
  }
4522
5247
  function extractVolumeSnapshot(world, assets, worldInternal) {
@@ -5178,6 +5903,6 @@ var ProbeBlendSceneProjection = class {
5178
5903
  }
5179
5904
  };
5180
5905
 
5181
- export { InstanceBoundsCache, OcclusionRenderRuntime, PROBE_MAX_CONTRIBUTORS, ProbeBlendSceneProjection, SKYLIGHT_RECOVERY_FALLBACK, admitProbeContributors, blendLightProbes, buildRectAreaWorldFrame, createCookieProjectionMatrixData, createExtendedLightingState, extractFrames, fingerprintNumericArray, glyphTextLayoutSystem, primitiveKey, primitiveKeyId, projectExtendedLightingInspection, promoteExtendedLightingCandidate, recordExtendedLightingFailure, rectAreaFacesPoint, scaledProbeWeight, setOcclusionRuntimeTestHooks, viewKey, viewKeyId };
5182
- //# sourceMappingURL=chunk-VSL23LZE.mjs.map
5183
- //# sourceMappingURL=chunk-VSL23LZE.mjs.map
5906
+ export { InstanceBoundsCache, OcclusionRenderRuntime, PROBE_MAX_CONTRIBUTORS, ProbeBlendSceneProjection, SKYLIGHT_RECOVERY_FALLBACK, SSR_HISTORY_FORMAT, SsrHistoryOwner, admitProbeContributors, blendLightProbes, buildRectAreaWorldFrame, buildShadowFrusta, createCookieProjectionMatrixData, createExtendedLightingState, createSsrHistoryOwner, createSsrSpatialResources, estimateSsrSpatialMemory, extractFrames, fingerprintNumericArray, glyphTextLayoutSystem, primitiveKey, primitiveKeyId, projectExtendedLightingInspection, promoteExtendedLightingCandidate, recordExtendedLightingFailure, rectAreaFacesPoint, scaledProbeWeight, setOcclusionRuntimeTestHooks, viewKey, viewKeyId };
5907
+ //# sourceMappingURL=chunk-C3DDSXYK.mjs.map
5908
+ //# sourceMappingURL=chunk-C3DDSXYK.mjs.map