@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
@@ -9,13 +9,12 @@
9
9
  // >= 8` — i.e. WebGPU spec default device).
10
10
  // One shared GPU buffer grows at 1.5x (Bevy skin.rs alignment,
11
11
  // plan-strategy D-4). Every entity's slice is `{ buffer: shared,
12
- // byteOffset: cursor }`. Record-stage builds ONE BG against the
13
- // shared buffer + `bindingWindowBytes` entry size; per-draw
14
- // `setBindGroup(_, bg, [_, dynOffset = slice.byteOffset])` slides
15
- // the static window across the buffer. WebGPU rule
16
- // `dynOffset + entry.size <= buffer.size` is satisfied because the
17
- // allocator extends `buffer.size` to `cursor + bindingWindowBytes`
18
- // after every slice.
12
+ // byteOffset: cursor }`. The direct CPU caster keeps the fixed
13
+ // `bindingWindowBytes` view and dynamic offset; the scene-index GPU
14
+ // projection binds the complete arena and addresses this slice through
15
+ // `InstanceData.customDataStart`. WebGPU's dynamic-offset bound remains
16
+ // satisfied for the direct path because the allocator extends
17
+ // `buffer.size` to `cursor + bindingWindowBytes` after every slice.
19
18
  //
20
19
  // UNIFORM PATH (`useStorageBuffer = false`, browser uniform fallback —
21
20
  // `maxStorageBuffersPerShaderStage = 0`).
@@ -29,12 +28,12 @@
29
28
  // BG (cached per-buffer pointer; pool reuse keeps createBuffer
30
29
  // amortized across frames).
31
30
  //
32
- // Concept that does NOT branch by path: `bindingWindowBytes`. It is
33
- // the static `pbr-skin-mesh-array-bgl @binding(1)` BG entry size,
34
- // identical on both paths (WGSL declares the same layout). Record-
35
- // stage uses it verbatim when constructing the BG. dynOffset[1]
36
- // on the uniform path is always 0 (entry size already equals buffer
37
- // size); on the storage path it walks 0, 1536, 3072, ... .
31
+ // Concept that does NOT branch by allocator path: `bindingWindowBytes`.
32
+ // It is the static direct/residual `pbr-skin-mesh-array-bgl @binding(1)`
33
+ // entry size, identical for the fixed-window WGSL layout. dynOffset[1]
34
+ // on the uniform path is always 0; on the storage direct path it walks
35
+ // aligned slices. The scene-index GPU path intentionally binds the whole
36
+ // storage arena and uses `customDataStart` rather than this fixed window.
38
37
  //
39
38
  // CPU pre-multiply (path-agnostic): writeJointPalette(slice, ibm, jointWorld)
40
39
  // -> mat4 per joint: M_i = joint_world_i * IBM_i
@@ -52,7 +51,11 @@ import {
52
51
  GPU_BUFFER_USAGE_STORAGE,
53
52
  GPU_BUFFER_USAGE_UNIFORM,
54
53
  } from '../gpu-usage';
55
- import type { SkinPaletteSlice } from './skin-palette-types';
54
+ import type {
55
+ SkinPaletteDirtyRange,
56
+ SkinPaletteReceipt,
57
+ SkinPaletteSlice,
58
+ } from './skin-palette-types';
56
59
 
57
60
  const MAT4_BYTES = 64; // 16 f32 * 4 bytes
58
61
  // MAX_JOINTS = 255 matches `pbr-skin-mesh-array-bgl @binding(1)` static BG
@@ -71,11 +74,18 @@ const BINDING_WINDOW_BYTES = MAX_JOINTS * MAT4_BYTES; // 16320
71
74
  // aligned` at draw time.
72
75
  const PALETTE_OFFSET_ALIGN = 256;
73
76
 
77
+ function alignedPaletteBytes(jointCount: number): number {
78
+ return (jointCount * MAT4_BYTES + (PALETTE_OFFSET_ALIGN - 1)) & ~(PALETTE_OFFSET_ALIGN - 1);
79
+ }
80
+
74
81
  export interface SkinPaletteAllocator {
82
+ /** Monotonic successful GPU content writes, independent of allocation identity. */
83
+ readonly contentRevision: number;
75
84
  /**
76
- * Static BG entry size for `pbr-skin-mesh-array-bgl @binding(1)`. Always
77
- * `MAX_JOINTS * 64 = 16320`; consumers (record stage) bind this size
78
- * when building the BG. Path-independent.
85
+ * Static BG entry size for the direct/residual
86
+ * `pbr-skin-mesh-array-bgl @binding(1)` path. Always `MAX_JOINTS * 64 =
87
+ * 16320`; the scene-index GPU path binds the complete storage arena
88
+ * instead. Path-independent for the fixed-window consumer.
79
89
  */
80
90
  readonly bindingWindowBytes: number;
81
91
  /**
@@ -86,6 +96,31 @@ export interface SkinPaletteAllocator {
86
96
  * `slice.buffer` identity (shared vs per-entity), not this flag.
87
97
  */
88
98
  readonly useStorageBuffer: boolean;
99
+ /** Allocate or reuse a persistent identity/generation-scoped palette range. */
100
+ allocatePersistentSlice(input: {
101
+ readonly identity: string;
102
+ readonly generation: number;
103
+ readonly jointCount: number;
104
+ readonly bounds?: Float32Array;
105
+ }): SkinPaletteReceipt;
106
+ /**
107
+ * Compare the producer's current joint matrices with the last observed
108
+ * pose and mark only changed joints dirty. The allocator owns this small
109
+ * pose observation cache so extract does not grow a second palette registry.
110
+ */
111
+ observePersistentJoints(
112
+ identity: string,
113
+ ibms: readonly Float32Array[],
114
+ jointWorlds: readonly Mat4[],
115
+ ): readonly number[];
116
+ /** Mark producer-owned joints dirty; adjacent joints are merged on receipt. */
117
+ markDirtyJoints(identity: string, joints: readonly number[]): void;
118
+ /** Start a frame without discarding persistent ranges or their fences. */
119
+ beginFrame(): void;
120
+ /** Reconcile persistent identities after the frame's extract pass. */
121
+ endFrame(): void;
122
+ /** Retire one producer identity after its owning scene is detached. */
123
+ releasePersistentSlice(identity: string): void;
89
124
  /**
90
125
  * Allocate a slice for `jointCount` joints. Returns the buffer + byte
91
126
  * offset the record stage should bind. Storage path returns the same
@@ -98,12 +133,6 @@ export interface SkinPaletteAllocator {
98
133
  * `device.limits.maxStorageBufferBindingSize`
99
134
  */
100
135
  allocateSlice(jointCount: number): SkinPaletteSlice;
101
- /** Allocate one stable slice for a retained render source. */
102
- allocateSliceFor(key: string, jointCount: number): SkinPaletteSlice;
103
- /** Release a stable slice when its render source leaves the scene. */
104
- releaseSliceFor(key: string): void;
105
- /** Reconcile stable slices after a full render-source extraction. */
106
- retainSliceKeys(keys: ReadonlySet<string>): void;
107
136
  /**
108
137
  * Write joint matrices into the slice's buffer at the slice's offset.
109
138
  * Computes M_i = jointWorldTransforms[i] * ibm[i] per joint.
@@ -118,12 +147,20 @@ export interface SkinPaletteAllocator {
118
147
  ibms: readonly Float32Array[],
119
148
  jointWorlds: readonly Mat4[],
120
149
  ): void;
150
+ /** Write only the dirty ranges carried by a persistent receipt. */
151
+ writePersistentJointPalette(
152
+ receipt: SkinPaletteReceipt,
153
+ ibms: readonly Float32Array[],
154
+ jointWorlds: readonly Mat4[],
155
+ ): void;
121
156
  /**
122
157
  * Reset for next frame. Storage path: cursor rewinds, shared buffer
123
158
  * stays. Uniform path: per-entity buffer cursor rewinds (pool entries
124
159
  * stay allocated and round-robin to the next frame's first entity).
125
160
  */
126
161
  resetForFrame(): void;
162
+ /** Release all allocator-owned GPU buffers during renderer teardown. */
163
+ dispose(): void;
127
164
  }
128
165
 
129
166
  export function createSkinPaletteAllocator(
@@ -135,16 +172,7 @@ export function createSkinPaletteAllocator(
135
172
  let storageBuffer: Buffer | null = null;
136
173
  let storageCapacity = 0;
137
174
  let storageCursor = 0;
138
- let stableStorageCursor = 0;
139
- const stableSlices = new Map<string, SkinPaletteSlice>();
140
- const stableUniformBuffers = new Map<string, Buffer>();
141
- const storageBufferCapacities = new WeakMap<Buffer, number>();
142
- const stableFreeRanges: Array<{
143
- start: number;
144
- count: number;
145
- buffer: Buffer;
146
- capacity: number;
147
- }> = [];
175
+ let contentRevision = 0;
148
176
 
149
177
  // Uniform path: per-entity buffer pool. `pool` is the pre-allocated
150
178
  // 16320 B UBO ring; `poolCursor` advances per allocateSlice within a
@@ -154,6 +182,347 @@ export function createSkinPaletteAllocator(
154
182
  // bounded by maxUniformBufferBindingSize (>= 16384 by spec floor).
155
183
  const pool: Buffer[] = [];
156
184
  let poolCursor = 0;
185
+ const persistentUniformBuffers = new Map<string, Buffer>();
186
+
187
+ interface PersistentAllocation {
188
+ readonly identity: string;
189
+ readonly generation: number;
190
+ readonly jointCount: number;
191
+ readonly byteSize: number;
192
+ slice: SkinPaletteSlice;
193
+ readonly fence: number;
194
+ readonly bounds?: Float32Array;
195
+ dirtyJoints: Set<number>;
196
+ }
197
+
198
+ /**
199
+ * Receipts retain the allocation owner rather than copying its buffer
200
+ * handle. A same-frame arena grow rebases every active allocation; the
201
+ * getter keeps receipts already handed to extract/record on that one
202
+ * current buffer instead of leaving an earlier draw bound to a retired
203
+ * generation.
204
+ */
205
+ function persistentReceipt(
206
+ allocation: PersistentAllocation,
207
+ dirtyRanges: readonly SkinPaletteDirtyRange[],
208
+ uploadBytes: number,
209
+ retiredByteOffset?: number,
210
+ ): SkinPaletteReceipt {
211
+ return {
212
+ get buffer() {
213
+ return allocation.slice.buffer;
214
+ },
215
+ get byteOffset() {
216
+ return allocation.slice.byteOffset;
217
+ },
218
+ jointCount: allocation.slice.jointCount,
219
+ identity: allocation.identity,
220
+ generation: allocation.generation,
221
+ fence: allocation.fence,
222
+ customDataStart: useStorageBuffer ? allocation.slice.byteOffset / MAT4_BYTES : 0,
223
+ storageOrUniform: useStorageBuffer ? 'storage' : 'uniform',
224
+ ...(allocation.bounds === undefined ? {} : { bounds: new Float32Array(allocation.bounds) }),
225
+ dirtyRanges,
226
+ uploadBytes,
227
+ ...(retiredByteOffset === undefined ? {} : { retiredByteOffset }),
228
+ };
229
+ }
230
+ const persistent = new Map<string, PersistentAllocation>();
231
+ interface StorageRange {
232
+ buffer: Buffer;
233
+ offset: number;
234
+ byteSize: number;
235
+ }
236
+ const freeStorageRanges: StorageRange[] = [];
237
+ const pendingStorageRetirements = new Set<StorageRange>();
238
+ const destroyedBuffers = new Set<Buffer>();
239
+ let allocatorDisposed = false;
240
+ const pendingDirty = new Map<string, Set<number>>();
241
+ const observedPose = new Map<string, readonly Float32Array[]>();
242
+ const frameSeenPersistent = new Set<string>();
243
+ let persistentCursor = 0;
244
+ let persistentFence = 0;
245
+
246
+ const queueWriteBuffer = (buffer: Buffer, byteOffset: number, payload: Float32Array): void => {
247
+ const result = device.queue.writeBuffer(buffer, byteOffset, payload);
248
+ if (!result.ok) throw result.error;
249
+ contentRevision += 1;
250
+ };
251
+
252
+ function normalizedDirtyRanges(
253
+ allocation: PersistentAllocation,
254
+ ): readonly SkinPaletteDirtyRange[] {
255
+ const joints = [...allocation.dirtyJoints]
256
+ .filter((joint) => joint >= 0 && joint < allocation.jointCount)
257
+ .sort((left, right) => left - right);
258
+ const ranges: SkinPaletteDirtyRange[] = [];
259
+ for (const joint of joints) {
260
+ const previous = ranges[ranges.length - 1];
261
+ if (previous !== undefined && previous.startJoint + previous.jointCount === joint) {
262
+ ranges[ranges.length - 1] = {
263
+ startJoint: previous.startJoint,
264
+ jointCount: previous.jointCount + 1,
265
+ };
266
+ } else {
267
+ ranges.push({ startJoint: joint, jointCount: 1 });
268
+ }
269
+ }
270
+ return Object.freeze(ranges);
271
+ }
272
+
273
+ function mergeFreeStorageRange(range: StorageRange): void {
274
+ if (allocatorDisposed || storageBuffer !== range.buffer || range.byteSize <= 0) return;
275
+ freeStorageRanges.push({ ...range });
276
+ freeStorageRanges.sort((left, right) => left.offset - right.offset);
277
+ for (let index = freeStorageRanges.length - 1; index > 0; index -= 1) {
278
+ const current = freeStorageRanges[index];
279
+ const previous = freeStorageRanges[index - 1];
280
+ if (current === undefined || previous === undefined) continue;
281
+ if (previous.offset + previous.byteSize !== current.offset) continue;
282
+ previous.byteSize += current.byteSize;
283
+ freeStorageRanges.splice(index, 1);
284
+ }
285
+ }
286
+
287
+ function retireStorageRange(range: StorageRange): void {
288
+ if (allocatorDisposed) return;
289
+ pendingStorageRetirements.add(range);
290
+ void device.queue.onSubmittedWorkDone().then(
291
+ () => {
292
+ pendingStorageRetirements.delete(range);
293
+ mergeFreeStorageRange(range);
294
+ },
295
+ () => {
296
+ pendingStorageRetirements.delete(range);
297
+ mergeFreeStorageRange(range);
298
+ },
299
+ );
300
+ }
301
+
302
+ function takeFreeStorageRange(byteSize: number): StorageRange | undefined {
303
+ if (!useStorageBuffer || storageBuffer === null) return undefined;
304
+ let candidateIndex = -1;
305
+ for (let index = 0; index < freeStorageRanges.length; index += 1) {
306
+ const candidate = freeStorageRanges[index];
307
+ if (
308
+ candidate !== undefined &&
309
+ candidate.buffer === storageBuffer &&
310
+ candidate.byteSize >= byteSize
311
+ ) {
312
+ candidateIndex = index;
313
+ break;
314
+ }
315
+ }
316
+ if (candidateIndex < 0) return undefined;
317
+ const candidate = freeStorageRanges[candidateIndex];
318
+ if (candidate === undefined) return undefined;
319
+ freeStorageRanges.splice(candidateIndex, 1);
320
+ if (candidate.byteSize > byteSize) {
321
+ freeStorageRanges.push({
322
+ buffer: candidate.buffer,
323
+ offset: candidate.offset + byteSize,
324
+ byteSize: candidate.byteSize - byteSize,
325
+ });
326
+ }
327
+ return { buffer: candidate.buffer, offset: candidate.offset, byteSize };
328
+ }
329
+
330
+ function destroyBufferOnce(buffer: Buffer): void {
331
+ if (destroyedBuffers.has(buffer)) return;
332
+ destroyedBuffers.add(buffer);
333
+ device.destroyBuffer(buffer);
334
+ }
335
+
336
+ function allocatePersistentSlice(input: {
337
+ readonly identity: string;
338
+ readonly generation: number;
339
+ readonly jointCount: number;
340
+ readonly bounds?: Float32Array;
341
+ }): SkinPaletteReceipt {
342
+ frameSeenPersistent.add(input.identity);
343
+ if (
344
+ !Number.isInteger(input.jointCount) ||
345
+ input.jointCount <= 0 ||
346
+ input.jointCount > MAX_JOINTS
347
+ ) {
348
+ throw new RangeError(`skin joint count must be between 1 and ${MAX_JOINTS}`);
349
+ }
350
+ const prior = persistent.get(input.identity);
351
+ if (
352
+ prior !== undefined &&
353
+ prior.generation === input.generation &&
354
+ prior.jointCount === input.jointCount
355
+ ) {
356
+ const dirtyRanges = normalizedDirtyRanges(prior);
357
+ const uploadBytes = dirtyRanges.reduce(
358
+ (total, range) => total + range.jointCount * MAT4_BYTES,
359
+ 0,
360
+ );
361
+ // Observation happens before allocation during extract. Consume the
362
+ // producer-owned dirty set exactly once; the receipt carries the write
363
+ // ranges to the palette writer below.
364
+ prior.dirtyJoints.clear();
365
+ return persistentReceipt(prior, dirtyRanges, uploadBytes);
366
+ }
367
+ const retiredByteOffset = prior?.slice.byteOffset;
368
+ if (prior !== undefined) {
369
+ persistent.delete(input.identity);
370
+ if (useStorageBuffer) {
371
+ retireStorageRange({
372
+ buffer: prior.slice.buffer,
373
+ offset: prior.slice.byteOffset,
374
+ byteSize: prior.byteSize,
375
+ });
376
+ }
377
+ }
378
+ let slice: SkinPaletteSlice;
379
+ if (useStorageBuffer) {
380
+ const byteSize = alignedPaletteBytes(input.jointCount);
381
+ const recycled = takeFreeStorageRange(byteSize);
382
+ if (recycled !== undefined) {
383
+ slice = {
384
+ jointCount: input.jointCount,
385
+ byteOffset: recycled.offset,
386
+ buffer: recycled.buffer,
387
+ };
388
+ } else {
389
+ const offset = persistentCursor;
390
+ const needed = offset + BINDING_WINDOW_BYTES;
391
+ ensureStorageCapacity(needed);
392
+ // biome-ignore lint/style/noNonNullAssertion: ensureStorageCapacity creates the buffer
393
+ const buffer = storageBuffer!;
394
+ persistentCursor = offset + byteSize;
395
+ slice = { jointCount: input.jointCount, byteOffset: offset, buffer };
396
+ }
397
+ } else {
398
+ let buffer = persistentUniformBuffers.get(input.identity);
399
+ if (buffer === undefined) {
400
+ if (BINDING_WINDOW_BYTES > maxBindingSize) {
401
+ throw new SkinPaletteOverflowError(BINDING_WINDOW_BYTES, maxBindingSize);
402
+ }
403
+ const created = device.createBuffer({
404
+ label: 'skin-palette-persistent',
405
+ size: BINDING_WINDOW_BYTES,
406
+ usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
407
+ mappedAtCreation: false,
408
+ });
409
+ if (!created.ok) throw created.error;
410
+ buffer = created.value;
411
+ persistentUniformBuffers.set(input.identity, buffer);
412
+ }
413
+ slice = { jointCount: input.jointCount, byteOffset: 0, buffer };
414
+ }
415
+ // A replacement generation owns a fresh slice. Even when the producer
416
+ // pose is unchanged, the new address has no committed GPU contents, so it
417
+ // must receive a complete upload before the receipt is published.
418
+ const carriedDirty =
419
+ prior !== undefined
420
+ ? new Set(Array.from({ length: input.jointCount }, (_, index) => index))
421
+ : (pendingDirty.get(input.identity) ??
422
+ new Set(Array.from({ length: input.jointCount }, (_, index) => index)));
423
+ const allocation: PersistentAllocation = {
424
+ identity: input.identity,
425
+ generation: input.generation,
426
+ jointCount: input.jointCount,
427
+ byteSize: alignedPaletteBytes(input.jointCount),
428
+ slice,
429
+ fence: ++persistentFence,
430
+ ...(input.bounds === undefined ? {} : { bounds: new Float32Array(input.bounds) }),
431
+ dirtyJoints: new Set(carriedDirty),
432
+ };
433
+ pendingDirty.delete(input.identity);
434
+ persistent.set(input.identity, allocation);
435
+ const dirtyRanges = normalizedDirtyRanges(allocation);
436
+ const uploadBytes = dirtyRanges.reduce(
437
+ (total, range) => total + range.jointCount * MAT4_BYTES,
438
+ 0,
439
+ );
440
+ allocation.dirtyJoints.clear();
441
+ return persistentReceipt(allocation, dirtyRanges, uploadBytes, retiredByteOffset);
442
+ }
443
+
444
+ function markDirtyJoints(identity: string, joints: readonly number[]): void {
445
+ const allocation = persistent.get(identity);
446
+ const dirty = allocation?.dirtyJoints ?? pendingDirty.get(identity) ?? new Set<number>();
447
+ for (const joint of joints) {
448
+ if (
449
+ Number.isInteger(joint) &&
450
+ joint >= 0 &&
451
+ (allocation === undefined || joint < allocation.jointCount)
452
+ ) {
453
+ dirty.add(joint);
454
+ }
455
+ }
456
+ if (allocation === undefined) pendingDirty.set(identity, dirty);
457
+ }
458
+
459
+ function releasePersistentSlice(identity: string): void {
460
+ const allocation = persistent.get(identity);
461
+ persistent.delete(identity);
462
+ pendingDirty.delete(identity);
463
+ observedPose.delete(identity);
464
+ if (allocation === undefined) return;
465
+ if (useStorageBuffer) {
466
+ retireStorageRange({
467
+ buffer: allocation.slice.buffer,
468
+ offset: allocation.slice.byteOffset,
469
+ byteSize: allocation.byteSize,
470
+ });
471
+ return;
472
+ }
473
+ const buffer = persistentUniformBuffers.get(identity);
474
+ if (buffer === undefined) return;
475
+ persistentUniformBuffers.delete(identity);
476
+ void device.queue.onSubmittedWorkDone().then(
477
+ () => destroyBufferOnce(buffer),
478
+ () => destroyBufferOnce(buffer),
479
+ );
480
+ }
481
+
482
+ function observePersistentJoints(
483
+ identity: string,
484
+ ibms: readonly Float32Array[],
485
+ jointWorlds: readonly Mat4[],
486
+ ): readonly number[] {
487
+ const count = Math.min(ibms.length, jointWorlds.length);
488
+ const previous = observedPose.get(identity);
489
+ const next: Float32Array[] = new Array(count);
490
+ const changed: number[] = [];
491
+ const temp = mat4.create();
492
+ const ibm = mat4.create();
493
+ for (let index = 0; index < count; index += 1) {
494
+ const ibmFlat = ibms[index];
495
+ const jointWorld = jointWorlds[index];
496
+ if (ibmFlat === undefined || jointWorld === undefined) continue;
497
+ for (let lane = 0; lane < 16; lane += 1) ibm[lane] = ibmFlat[lane] ?? 0;
498
+ mat4.multiply(temp, jointWorld, ibm);
499
+ const copy = new Float32Array(temp);
500
+ next[index] = copy;
501
+ const prior = previous?.[index];
502
+ if (
503
+ prior === undefined ||
504
+ prior.length !== copy.length ||
505
+ prior.some((v, lane) => v !== copy[lane])
506
+ ) {
507
+ changed.push(index);
508
+ }
509
+ }
510
+ observedPose.set(identity, Object.freeze(next));
511
+ if (changed.length > 0) markDirtyJoints(identity, changed);
512
+ return Object.freeze(changed);
513
+ }
514
+
515
+ function beginFrame(): void {
516
+ frameSeenPersistent.clear();
517
+ persistentCursor = Math.max(persistentCursor, storageCursor);
518
+ }
519
+
520
+ function endFrame(): void {
521
+ for (const identity of [...persistent.keys()]) {
522
+ if (!frameSeenPersistent.has(identity)) releasePersistentSlice(identity);
523
+ }
524
+ frameSeenPersistent.clear();
525
+ }
157
526
 
158
527
  function ensureStorageCapacity(needed: number): void {
159
528
  if (storageBuffer !== null && needed <= storageCapacity) return;
@@ -172,12 +541,45 @@ export function createSkinPaletteAllocator(
172
541
  mappedAtCreation: false,
173
542
  });
174
543
  if (!bufRes.ok) throw bufRes.error;
544
+ const previous = storageBuffer;
175
545
  storageBuffer = bufRes.value;
176
546
  storageCapacity = newCapacity;
177
- storageBufferCapacities.set(storageBuffer, newCapacity);
547
+ for (const range of freeStorageRanges) {
548
+ if (range.buffer === previous) range.buffer = storageBuffer;
549
+ }
550
+ for (const range of pendingStorageRetirements) {
551
+ if (range.buffer === previous) range.buffer = storageBuffer;
552
+ }
553
+ // A persistent arena can grow after earlier identities have already been
554
+ // published. Rebase those slices into the new arena and restore their
555
+ // last producer-observed matrices before the next frame can bind it;
556
+ // otherwise one frame would bind two palette buffers through one BG.
557
+ for (const allocation of persistent.values()) {
558
+ const pose = observedPose.get(allocation.identity);
559
+ if (pose !== undefined) {
560
+ const payload = new Float32Array(allocation.jointCount * 16);
561
+ for (let joint = 0; joint < allocation.jointCount; joint += 1) {
562
+ const matrix = pose[joint];
563
+ if (matrix !== undefined) payload.set(matrix, joint * 16);
564
+ }
565
+ queueWriteBuffer(storageBuffer, allocation.slice.byteOffset, payload);
566
+ }
567
+ allocation.slice = { ...allocation.slice, buffer: storageBuffer };
568
+ }
569
+ if (previous !== null) {
570
+ void device.queue.onSubmittedWorkDone().then(
571
+ () => destroyBufferOnce(previous),
572
+ () => destroyBufferOnce(previous),
573
+ );
574
+ }
178
575
  }
179
576
 
180
- function createUniformBuffer(): Buffer {
577
+ function acquirePoolBuffer(): Buffer {
578
+ if (poolCursor < pool.length) {
579
+ const reused = pool[poolCursor];
580
+ // biome-ignore lint/style/noNonNullAssertion: poolCursor < pool.length guarantees the slot is set
581
+ return reused!;
582
+ }
181
583
  if (BINDING_WINDOW_BYTES > maxBindingSize) {
182
584
  throw new SkinPaletteOverflowError(BINDING_WINDOW_BYTES, maxBindingSize);
183
585
  }
@@ -188,20 +590,10 @@ export function createSkinPaletteAllocator(
188
590
  mappedAtCreation: false,
189
591
  });
190
592
  if (!bufRes.ok) throw bufRes.error;
593
+ pool.push(bufRes.value);
191
594
  return bufRes.value;
192
595
  }
193
596
 
194
- function acquirePoolBuffer(): Buffer {
195
- if (poolCursor < pool.length) {
196
- const reused = pool[poolCursor];
197
- // biome-ignore lint/style/noNonNullAssertion: poolCursor < pool.length guarantees the slot is set
198
- return reused!;
199
- }
200
- const buffer = createUniformBuffer();
201
- pool.push(buffer);
202
- return buffer;
203
- }
204
-
205
597
  function allocateSlice(jointCount: number): SkinPaletteSlice {
206
598
  if (useStorageBuffer) {
207
599
  // Storage path: shared buffer + dynOffset window.
@@ -231,103 +623,6 @@ export function createSkinPaletteAllocator(
231
623
  return { jointCount, byteOffset: 0, buffer };
232
624
  }
233
625
 
234
- function allocateSliceFor(key: string, jointCount: number): SkinPaletteSlice {
235
- const existing = stableSlices.get(key);
236
- if (existing !== undefined && existing.jointCount === jointCount) return existing;
237
- if (existing !== undefined) releaseSliceFor(key);
238
- if (useStorageBuffer) {
239
- const span =
240
- (jointCount * MAT4_BYTES + (PALETTE_OFFSET_ALIGN - 1)) & ~(PALETTE_OFFSET_ALIGN - 1);
241
- const freeIndex = stableFreeRanges.findIndex(
242
- (range) =>
243
- range.buffer === storageBuffer &&
244
- range.count >= span &&
245
- range.start + BINDING_WINDOW_BYTES <= range.capacity,
246
- );
247
- let offset: number;
248
- let buffer: Buffer;
249
- if (freeIndex >= 0) {
250
- const range = stableFreeRanges[freeIndex];
251
- if (range === undefined) throw new Error('Skin palette free range disappeared.');
252
- offset = range.start;
253
- buffer = range.buffer;
254
- if (range.count === span) stableFreeRanges.splice(freeIndex, 1);
255
- else {
256
- stableFreeRanges[freeIndex] = {
257
- ...range,
258
- start: range.start + span,
259
- count: range.count - span,
260
- };
261
- }
262
- } else {
263
- offset = stableStorageCursor;
264
- ensureStorageCapacity(offset + BINDING_WINDOW_BYTES);
265
- const currentBuffer = storageBuffer;
266
- if (currentBuffer === null) throw new Error('Skin palette storage buffer was not created.');
267
- buffer = currentBuffer;
268
- stableStorageCursor = offset + span;
269
- }
270
- const slice = { jointCount, byteOffset: offset, buffer };
271
- stableSlices.set(key, slice);
272
- return slice;
273
- }
274
- let buffer = stableUniformBuffers.get(key);
275
- if (buffer === undefined) {
276
- // Stable slices have a lifetime longer than the frame pool. Allocate a
277
- // dedicated UBO so resetForFrame() can never hand it to another entity.
278
- buffer = createUniformBuffer();
279
- stableUniformBuffers.set(key, buffer);
280
- }
281
- const slice = { jointCount, byteOffset: 0, buffer };
282
- stableSlices.set(key, slice);
283
- return slice;
284
- }
285
-
286
- function releaseSliceFor(key: string): void {
287
- const slice = stableSlices.get(key);
288
- if (slice === undefined) return;
289
- stableSlices.delete(key);
290
- if (!useStorageBuffer) {
291
- stableUniformBuffers.delete(key);
292
- device.destroyBuffer(slice.buffer);
293
- return;
294
- }
295
- const count =
296
- (slice.jointCount * MAT4_BYTES + (PALETTE_OFFSET_ALIGN - 1)) & ~(PALETTE_OFFSET_ALIGN - 1);
297
- stableFreeRanges.push({
298
- start: slice.byteOffset,
299
- count,
300
- buffer: slice.buffer,
301
- capacity: storageBufferCapacities.get(slice.buffer) ?? storageCapacity,
302
- });
303
- stableFreeRanges.sort((left, right) => left.start - right.start);
304
- for (let index = stableFreeRanges.length - 1; index > 0; index -= 1) {
305
- const current = stableFreeRanges[index];
306
- const previous = stableFreeRanges[index - 1];
307
- if (
308
- current === undefined ||
309
- previous === undefined ||
310
- current.buffer !== previous.buffer ||
311
- previous.start + previous.count !== current.start
312
- ) {
313
- continue;
314
- }
315
- stableFreeRanges[index - 1] = {
316
- start: previous.start,
317
- count: previous.count + current.count,
318
- buffer: previous.buffer,
319
- capacity: previous.capacity,
320
- };
321
- stableFreeRanges.splice(index, 1);
322
- }
323
- }
324
-
325
- function retainSliceKeys(keys: ReadonlySet<string>): void {
326
- for (const key of stableSlices.keys()) {
327
- if (!keys.has(key)) releaseSliceFor(key);
328
- }
329
- }
330
-
331
626
  function writeJointPalette(
332
627
  slice: SkinPaletteSlice,
333
628
  ibms: readonly Float32Array[],
@@ -351,8 +646,36 @@ export function createSkinPaletteAllocator(
351
646
  payload[base + j] = temp[j] ?? 0;
352
647
  }
353
648
  }
354
- const res = device.queue.writeBuffer(slice.buffer, slice.byteOffset, payload);
355
- if (!res.ok) throw res.error;
649
+ queueWriteBuffer(slice.buffer, slice.byteOffset, payload);
650
+ }
651
+
652
+ function writePersistentJointPalette(
653
+ receipt: SkinPaletteReceipt,
654
+ ibms: readonly Float32Array[],
655
+ jointWorlds: readonly Mat4[],
656
+ ): void {
657
+ if (receipt.uploadBytes === 0 || receipt.dirtyRanges.length === 0) return;
658
+ const temp = mat4.create();
659
+ const ibm = mat4.create();
660
+ for (const range of receipt.dirtyRanges) {
661
+ const count = Math.min(
662
+ range.jointCount,
663
+ ibms.length - range.startJoint,
664
+ jointWorlds.length - range.startJoint,
665
+ );
666
+ if (count <= 0) continue;
667
+ const payload = new Float32Array(count * 16);
668
+ for (let local = 0; local < count; local += 1) {
669
+ const index = range.startJoint + local;
670
+ const ibmFlat = ibms[index];
671
+ const jointWorld = jointWorlds[index];
672
+ if (ibmFlat === undefined || jointWorld === undefined) continue;
673
+ for (let lane = 0; lane < 16; lane += 1) ibm[lane] = ibmFlat[lane] ?? 0;
674
+ mat4.multiply(temp, jointWorld, ibm);
675
+ payload.set(temp, local * 16);
676
+ }
677
+ queueWriteBuffer(receipt.buffer, receipt.byteOffset + range.startJoint * MAT4_BYTES, payload);
678
+ }
356
679
  }
357
680
 
358
681
  function resetForFrame(): void {
@@ -360,14 +683,38 @@ export function createSkinPaletteAllocator(
360
683
  poolCursor = 0;
361
684
  }
362
685
 
686
+ function dispose(): void {
687
+ if (allocatorDisposed) return;
688
+ allocatorDisposed = true;
689
+ if (storageBuffer !== null) destroyBufferOnce(storageBuffer);
690
+ for (const buffer of pool) destroyBufferOnce(buffer);
691
+ for (const buffer of persistentUniformBuffers.values()) destroyBufferOnce(buffer);
692
+ storageBuffer = null;
693
+ persistent.clear();
694
+ pendingDirty.clear();
695
+ observedPose.clear();
696
+ persistentUniformBuffers.clear();
697
+ freeStorageRanges.length = 0;
698
+ pendingStorageRetirements.clear();
699
+ pool.length = 0;
700
+ }
701
+
363
702
  return {
703
+ get contentRevision() {
704
+ return contentRevision;
705
+ },
364
706
  bindingWindowBytes: BINDING_WINDOW_BYTES,
365
707
  useStorageBuffer,
708
+ allocatePersistentSlice,
709
+ observePersistentJoints,
710
+ markDirtyJoints,
711
+ releasePersistentSlice,
712
+ beginFrame,
713
+ endFrame,
366
714
  allocateSlice,
367
- allocateSliceFor,
368
- releaseSliceFor,
369
- retainSliceKeys,
370
715
  writeJointPalette,
716
+ writePersistentJointPalette,
371
717
  resetForFrame,
718
+ dispose,
372
719
  };
373
720
  }