@forgeax/engine-render 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. package/README.md +1374 -142
  2. package/dist/assembly/analytic-fog-registration.d.ts +3 -0
  3. package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
  4. package/dist/assembly/backend-contract.d.ts +2 -0
  5. package/dist/assembly/backend-contract.d.ts.map +1 -1
  6. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  7. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  8. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  9. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  10. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  11. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  12. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  13. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  15. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  16. package/dist/assembly/factory.d.ts +1 -1
  17. package/dist/assembly/factory.d.ts.map +1 -1
  18. package/dist/assembly/fxaa-registration.d.ts +4 -0
  19. package/dist/assembly/fxaa-registration.d.ts.map +1 -0
  20. package/dist/assembly/host-contract.d.ts +3 -3
  21. package/dist/assembly/host-contract.d.ts.map +1 -1
  22. package/dist/assembly/lod-observation.d.ts +4 -0
  23. package/dist/assembly/lod-observation.d.ts.map +1 -0
  24. package/dist/assembly/material/assembly.d.ts.map +1 -1
  25. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  26. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  27. package/dist/assembly/material-shader-policy.d.ts +16 -2
  28. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  29. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  30. package/dist/assembly/motion-blur-registration.d.ts +3 -0
  31. package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
  32. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  33. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  34. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  35. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  36. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  37. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  38. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  39. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  40. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  41. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  42. package/dist/assembly/renderer-inspection.d.ts +11 -0
  43. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  44. package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
  45. package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  47. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  48. package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
  49. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -1
  50. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  51. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  52. package/dist/assembly/webgpu-ready.d.ts +2 -2
  53. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  54. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  55. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  56. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  57. package/dist/assembly/webgpu-renderer.d.ts +1 -1
  58. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  59. package/dist/authoring.mjs +1 -1
  60. package/dist/barrel-distortion.d.ts +47 -0
  61. package/dist/barrel-distortion.d.ts.map +1 -0
  62. package/dist/bloom-admission.d.ts +13 -0
  63. package/dist/bloom-admission.d.ts.map +1 -0
  64. package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
  65. package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
  66. package/dist/{chunk-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
  67. package/dist/chunk-HEB564WF.mjs.map +1 -0
  68. package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
  69. package/dist/chunk-MKDIT2EM.mjs.map +1 -0
  70. package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
  71. package/dist/{chunk-S665NJNF.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
  72. package/dist/chunk-ODZWR6JQ.mjs +4927 -0
  73. package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
  74. package/dist/{chunk-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
  75. package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
  76. package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
  77. package/dist/chunk-UI5SFODX.mjs.map +1 -0
  78. package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
  79. package/dist/chunk-UINHLCZA.mjs.map +1 -0
  80. package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
  81. package/dist/chunk-WEX45HKH.mjs.map +1 -0
  82. package/dist/cloud/density.d.ts +55 -0
  83. package/dist/cloud/density.d.ts.map +1 -0
  84. package/dist/cloud/extract.d.ts +25 -0
  85. package/dist/cloud/extract.d.ts.map +1 -0
  86. package/dist/cloud/feature.d.ts +57 -0
  87. package/dist/cloud/feature.d.ts.map +1 -0
  88. package/dist/cloud/frame-context.d.ts +8 -0
  89. package/dist/cloud/frame-context.d.ts.map +1 -0
  90. package/dist/cloud/inspection.d.ts +59 -0
  91. package/dist/cloud/inspection.d.ts.map +1 -0
  92. package/dist/cloud/optics.d.ts +56 -0
  93. package/dist/cloud/optics.d.ts.map +1 -0
  94. package/dist/cloud/parameters.d.ts +73 -0
  95. package/dist/cloud/parameters.d.ts.map +1 -0
  96. package/dist/cloud/resources.d.ts +60 -0
  97. package/dist/cloud/resources.d.ts.map +1 -0
  98. package/dist/cloud/shadow.d.ts +42 -0
  99. package/dist/cloud/shadow.d.ts.map +1 -0
  100. package/dist/cloud/temporal.d.ts +74 -0
  101. package/dist/cloud/temporal.d.ts.map +1 -0
  102. package/dist/components/atmosphere.d.ts +2 -0
  103. package/dist/components/atmosphere.d.ts.map +1 -1
  104. package/dist/components/barrel-distortion.d.ts +13 -0
  105. package/dist/components/barrel-distortion.d.ts.map +1 -0
  106. package/dist/components/camera.d.ts +20 -4
  107. package/dist/components/camera.d.ts.map +1 -1
  108. package/dist/components/cloud-layer.d.ts +29 -0
  109. package/dist/components/cloud-layer.d.ts.map +1 -0
  110. package/dist/components/index.d.ts +2 -0
  111. package/dist/components/index.d.ts.map +1 -1
  112. package/dist/components/instances.d.ts +20 -6
  113. package/dist/components/instances.d.ts.map +1 -1
  114. package/dist/components/mesh-filter.d.ts +6 -5
  115. package/dist/components/mesh-filter.d.ts.map +1 -1
  116. package/dist/components/motion-blur.d.ts +1 -0
  117. package/dist/components/motion-blur.d.ts.map +1 -1
  118. package/dist/construct-renderer.d.ts +1 -1
  119. package/dist/construct-renderer.d.ts.map +1 -1
  120. package/dist/construct-renderer.mjs +9751 -3528
  121. package/dist/construct-renderer.mjs.map +1 -1
  122. package/dist/device/gpu-residency.d.ts +6 -0
  123. package/dist/device/gpu-residency.d.ts.map +1 -1
  124. package/dist/dynamic-geometry.d.ts +5 -1
  125. package/dist/dynamic-geometry.d.ts.map +1 -1
  126. package/dist/environment/analytic-fog.d.ts +6 -0
  127. package/dist/environment/analytic-fog.d.ts.map +1 -0
  128. package/dist/errors/cloud.d.ts +59 -0
  129. package/dist/errors/cloud.d.ts.map +1 -0
  130. package/dist/errors/render.d.ts +23 -5
  131. package/dist/errors/render.d.ts.map +1 -1
  132. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  133. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  134. package/dist/extract/camera.d.ts.map +1 -1
  135. package/dist/extract/contracts.d.ts +12 -1
  136. package/dist/extract/contracts.d.ts.map +1 -1
  137. package/dist/extract/environment.d.ts +2 -0
  138. package/dist/extract/environment.d.ts.map +1 -1
  139. package/dist/features/barrel-distortion.d.ts +29 -0
  140. package/dist/features/barrel-distortion.d.ts.map +1 -0
  141. package/dist/features/error-reporting.d.ts +17 -0
  142. package/dist/features/error-reporting.d.ts.map +1 -0
  143. package/dist/features/host.d.ts +15 -0
  144. package/dist/features/host.d.ts.map +1 -1
  145. package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
  146. package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
  147. package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
  148. package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
  149. package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
  150. package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
  151. package/dist/features/plan.d.ts +15 -4
  152. package/dist/features/plan.d.ts.map +1 -1
  153. package/dist/features/prepared-gpu-work.d.ts +9 -5
  154. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  155. package/dist/features/render-graph-compute.d.ts.map +1 -1
  156. package/dist/features/render-graph-contribution.d.ts +5 -0
  157. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  158. package/dist/features/render-graph-raster.d.ts +1 -0
  159. package/dist/features/render-graph-raster.d.ts.map +1 -1
  160. package/dist/features/targets.d.ts +2 -0
  161. package/dist/features/targets.d.ts.map +1 -1
  162. package/dist/features/types.d.ts +44 -0
  163. package/dist/features/types.d.ts.map +1 -1
  164. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  165. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  166. package/dist/gpu-dirty-ranges.d.ts +11 -0
  167. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  168. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  169. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  170. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  171. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  172. package/dist/gpu-driven/prepared-draw.d.ts +7 -0
  173. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  174. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  175. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  176. package/dist/gpu-driven/production-raster.d.ts +50 -4
  177. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  178. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  179. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  180. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  181. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  182. package/dist/gpu-driven/view-gpu.d.ts +35 -2
  183. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  184. package/dist/gpu-scene.d.ts +11 -1
  185. package/dist/gpu-scene.d.ts.map +1 -1
  186. package/dist/hdrp-buffers.d.ts +2 -2
  187. package/dist/hdrp-buffers.d.ts.map +1 -1
  188. package/dist/ibl/skylight-bind-group.d.ts +10 -1
  189. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  190. package/dist/index.d.ts +31 -8
  191. package/dist/index.d.ts.map +1 -1
  192. package/dist/index.mjs +258 -8
  193. package/dist/index.mjs.map +1 -1
  194. package/dist/inspection-types.d.ts +178 -3
  195. package/dist/inspection-types.d.ts.map +1 -1
  196. package/dist/instance-buffer-cache.d.ts +4 -4
  197. package/dist/instance-buffer-cache.d.ts.map +1 -1
  198. package/dist/instances.d.ts +49 -94
  199. package/dist/instances.d.ts.map +1 -1
  200. package/dist/internal.mjs +7 -7
  201. package/dist/pbr-pipeline.d.ts +19 -1
  202. package/dist/pbr-pipeline.d.ts.map +1 -1
  203. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  204. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  205. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  206. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  207. package/dist/pipeline/standard-output/types.d.ts +4 -2
  208. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  209. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  210. package/dist/pipeline/standard-post.d.ts +28 -19
  211. package/dist/pipeline/standard-post.d.ts.map +1 -1
  212. package/dist/pipeline-builder.d.ts +1 -1
  213. package/dist/pipeline-builder.d.ts.map +1 -1
  214. package/dist/pipeline-spec.d.ts +2 -2
  215. package/dist/plugin.d.ts.map +1 -1
  216. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  217. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  218. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  219. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  220. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  221. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  222. package/dist/record/fold-buckets.d.ts +95 -0
  223. package/dist/record/fold-buckets.d.ts.map +1 -0
  224. package/dist/record/fold-instance-buffer.d.ts +6 -0
  225. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  226. package/dist/record/frame-lighting.d.ts +1 -0
  227. package/dist/record/frame-lighting.d.ts.map +1 -1
  228. package/dist/record/frame-snapshot.d.ts +40 -3
  229. package/dist/record/frame-snapshot.d.ts.map +1 -1
  230. package/dist/record/frame-targets.d.ts.map +1 -1
  231. package/dist/record/frame.d.ts +14 -62
  232. package/dist/record/frame.d.ts.map +1 -1
  233. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  234. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  235. package/dist/record/gpu-timing.d.ts +8 -0
  236. package/dist/record/gpu-timing.d.ts.map +1 -1
  237. package/dist/record/main-pass-geometry.d.ts +21 -5
  238. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  239. package/dist/record/main-pass-material.d.ts +7 -1
  240. package/dist/record/main-pass-material.d.ts.map +1 -1
  241. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  242. package/dist/record/main-pass.d.ts +13 -2
  243. package/dist/record/main-pass.d.ts.map +1 -1
  244. package/dist/record/mesh-ssbo.d.ts +6 -5
  245. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  246. package/dist/record/motion-blur-receipt.d.ts +11 -0
  247. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  248. package/dist/record/probe-blend-buffer.d.ts +16 -0
  249. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  250. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  251. package/dist/record/render-context.d.ts +34 -31
  252. package/dist/record/render-context.d.ts.map +1 -1
  253. package/dist/record/shadow-pass.d.ts +2 -0
  254. package/dist/record/shadow-pass.d.ts.map +1 -1
  255. package/dist/record/skybox-post-pass.d.ts +6 -4
  256. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  257. package/dist/record/typed-frame-graph.d.ts +22 -2
  258. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  259. package/dist/record/view-ubo.d.ts +11 -3
  260. package/dist/record/view-ubo.d.ts.map +1 -1
  261. package/dist/record/volume-params.d.ts +9 -0
  262. package/dist/record/volume-params.d.ts.map +1 -0
  263. package/dist/recovery/render-system-candidate.d.ts +10 -0
  264. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  265. package/dist/reflection/record-owner.d.ts.map +1 -1
  266. package/dist/render-contract.d.ts +66 -8
  267. package/dist/render-contract.d.ts.map +1 -1
  268. package/dist/render-graph-primitives.d.ts.map +1 -1
  269. package/dist/render-pipeline.d.ts +106 -3
  270. package/dist/render-pipeline.d.ts.map +1 -1
  271. package/dist/render-system-extract-tail.d.ts +3 -2
  272. package/dist/render-system-extract-tail.d.ts.map +1 -1
  273. package/dist/render-system-extract.d.ts +24 -10
  274. package/dist/render-system-extract.d.ts.map +1 -1
  275. package/dist/render-system-presentation.d.ts +23 -0
  276. package/dist/render-system-presentation.d.ts.map +1 -0
  277. package/dist/render-system-producer-roots.d.ts +10 -0
  278. package/dist/render-system-producer-roots.d.ts.map +1 -0
  279. package/dist/render-system-residency.d.ts +12 -0
  280. package/dist/render-system-residency.d.ts.map +1 -0
  281. package/dist/render-system.d.ts +26 -15
  282. package/dist/render-system.d.ts.map +1 -1
  283. package/dist/scene/probe-blend.d.ts +27 -0
  284. package/dist/scene/probe-blend.d.ts.map +1 -1
  285. package/dist/scene/render-scene.d.ts +14 -5
  286. package/dist/scene/render-scene.d.ts.map +1 -1
  287. package/dist/ssao-buffers.d.ts +9 -0
  288. package/dist/ssao-buffers.d.ts.map +1 -1
  289. package/dist/surface/dynamic-input.d.ts +133 -0
  290. package/dist/surface/dynamic-input.d.ts.map +1 -0
  291. package/dist/surface/gpu-driven.d.ts +41 -0
  292. package/dist/surface/gpu-driven.d.ts.map +1 -0
  293. package/dist/surface/submission-observation.d.ts +136 -0
  294. package/dist/surface/submission-observation.d.ts.map +1 -0
  295. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  296. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  297. package/dist/temporal/frame.d.ts +7 -0
  298. package/dist/temporal/frame.d.ts.map +1 -1
  299. package/dist/temporal/gpu.d.ts +13 -1
  300. package/dist/temporal/gpu.d.ts.map +1 -1
  301. package/dist/temporal/index.mjs +5 -5
  302. package/dist/temporal/inspection.d.ts.map +1 -1
  303. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  304. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  305. package/dist/temporal/view.d.ts +6 -1
  306. package/dist/temporal/view.d.ts.map +1 -1
  307. package/dist/transmission/single-layer-medium.d.ts +89 -0
  308. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  309. package/dist/typed-render-graph-primitives.d.ts +24 -9
  310. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  311. package/dist/volume/component.d.ts +9 -5
  312. package/dist/volume/component.d.ts.map +1 -1
  313. package/dist/volume/extract.d.ts +1 -1
  314. package/dist/volume/extract.d.ts.map +1 -1
  315. package/dist/volume/inspection.d.ts +2 -0
  316. package/dist/volume/inspection.d.ts.map +1 -1
  317. package/dist/volume/passes.d.ts +4 -1
  318. package/dist/volume/passes.d.ts.map +1 -1
  319. package/dist/volume/resources.d.ts.map +1 -1
  320. package/dist/volume/temporal.d.ts +3 -1
  321. package/dist/volume/temporal.d.ts.map +1 -1
  322. package/package.json +22 -21
  323. package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
  324. package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
  325. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  326. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  327. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  328. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  329. package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
  330. package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
  331. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  332. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  333. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  334. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  335. package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
  336. package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
  337. package/src/__tests__/environment-selection.unit.test.ts +12 -0
  338. package/src/__tests__/factory-contract.integration.test.ts +626 -113
  339. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  340. package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
  341. package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +2 -1
  347. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  348. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
  349. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  350. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +7 -6
  351. package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
  352. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
  353. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  354. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  355. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  356. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  357. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  358. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  359. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  360. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
  361. package/src/__tests__/gpu-scene.unit.test.ts +210 -9
  362. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  363. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  364. package/src/__tests__/instances-store.unit.test.ts +105 -238
  365. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  366. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
  367. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  368. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  369. package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
  370. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  371. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  372. package/src/__tests__/motion-blur-compute.dawn.test.ts +589 -0
  373. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  374. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  375. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  376. package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
  377. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
  378. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  379. package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
  380. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  381. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  382. package/src/__tests__/public-surface.test-d.ts +8 -0
  383. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  384. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  385. package/src/__tests__/render-error-code-owner.test-d.ts +9 -0
  386. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  387. package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
  388. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  389. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  390. package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
  391. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  392. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  393. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +37 -6
  394. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  395. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  396. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  397. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
  398. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  399. package/src/__tests__/renderer-frame-transaction.integration.test.ts +33 -11
  400. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  401. package/src/__tests__/shader-manifest-fixture.ts +4 -4
  402. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  403. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  404. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  405. package/src/__tests__/skinned-shadow-caster.test.ts +17 -0
  406. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  407. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  408. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  409. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  410. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  411. package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
  412. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  413. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  414. package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
  415. package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
  416. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  417. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  418. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  419. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  420. package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
  421. package/src/__tests__/temporal-view.unit.test.ts +2 -1
  422. package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
  423. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  424. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  425. package/src/__tests__/volume-optics-oracle.unit.test.ts +7 -3
  426. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
  427. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  428. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  429. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  430. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +558 -68
  431. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
  432. package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
  433. package/src/assembly/analytic-fog-registration.ts +14 -0
  434. package/src/assembly/backend-contract.ts +30 -0
  435. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  436. package/src/assembly/canvas-draw-guard.ts +11 -0
  437. package/src/assembly/cloud-shadow-entry.ts +22 -0
  438. package/src/assembly/dynamic-geometry-host.ts +65 -37
  439. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  440. package/src/assembly/factory.ts +2 -30
  441. package/src/assembly/fxaa-registration.ts +17 -0
  442. package/src/assembly/host-contract.ts +3 -3
  443. package/src/assembly/lod-observation.ts +12 -0
  444. package/src/assembly/material/assembly.ts +25 -13
  445. package/src/assembly/material/pipeline-helpers.ts +53 -12
  446. package/src/assembly/material-shader-policy.ts +55 -0
  447. package/src/assembly/material-shader-prewarm.ts +21 -10
  448. package/src/assembly/motion-blur-registration.ts +17 -0
  449. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  450. package/src/assembly/recovery/renderer-recover.ts +41 -18
  451. package/src/assembly/render-feature-post-processes.ts +54 -0
  452. package/src/assembly/renderer-facade.ts +6 -1
  453. package/src/assembly/renderer-feature-inspection.ts +8 -2
  454. package/src/assembly/renderer-frame-transaction.ts +23 -0
  455. package/src/assembly/renderer-inspection.ts +28 -0
  456. package/src/assembly/skin-palette-owner.ts +1 -1
  457. package/src/assembly/temporal-post-process-prewarm.ts +40 -0
  458. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  459. package/src/assembly/webgpu-ready-contract.ts +8 -3
  460. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  461. package/src/assembly/webgpu-ready.ts +296 -306
  462. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  463. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  464. package/src/assembly/webgpu-renderer.ts +228 -281
  465. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  466. package/src/barrel-distortion.ts +247 -0
  467. package/src/bloom-admission.ts +21 -0
  468. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  469. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  470. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  471. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  472. package/src/cloud/density.ts +600 -0
  473. package/src/cloud/extract.ts +110 -0
  474. package/src/cloud/feature.ts +1810 -0
  475. package/src/cloud/frame-context.ts +42 -0
  476. package/src/cloud/inspection.ts +130 -0
  477. package/src/cloud/optics.ts +285 -0
  478. package/src/cloud/parameters.ts +255 -0
  479. package/src/cloud/resources.ts +122 -0
  480. package/src/cloud/shadow.ts +167 -0
  481. package/src/cloud/temporal.ts +226 -0
  482. package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
  483. package/src/components/atmosphere.ts +4 -0
  484. package/src/components/barrel-distortion.ts +46 -0
  485. package/src/components/camera.ts +66 -10
  486. package/src/components/cloud-layer.ts +47 -0
  487. package/src/components/index.ts +2 -0
  488. package/src/components/instances.ts +18 -45
  489. package/src/components/mesh-filter.ts +11 -9
  490. package/src/components/motion-blur.ts +1 -0
  491. package/src/components/sprite-instances.ts +1 -1
  492. package/src/construct-renderer.ts +1 -1
  493. package/src/device/gpu-residency.ts +56 -12
  494. package/src/dynamic-geometry.ts +12 -1
  495. package/src/environment/analytic-fog.ts +44 -0
  496. package/src/environment/background.ts +2 -2
  497. package/src/errors/cloud.ts +103 -0
  498. package/src/errors/render.ts +58 -8
  499. package/src/examples/single-layer-medium-surface.ts +59 -0
  500. package/src/extract/camera.ts +35 -8
  501. package/src/extract/contracts.ts +12 -0
  502. package/src/extract/environment.ts +4 -0
  503. package/src/features/barrel-distortion.ts +172 -0
  504. package/src/features/error-reporting.ts +98 -0
  505. package/src/features/host.ts +138 -24
  506. package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
  507. package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
  508. package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
  509. package/src/features/motion-blur/motion-blur-params.ts +70 -2
  510. package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
  511. package/src/features/plan.ts +33 -8
  512. package/src/features/prepared-gpu-work.ts +86 -35
  513. package/src/features/render-graph-compute.ts +13 -5
  514. package/src/features/render-graph-contribution.ts +11 -0
  515. package/src/features/render-graph-raster.ts +45 -3
  516. package/src/features/targets.ts +66 -0
  517. package/src/features/types.ts +47 -0
  518. package/src/fullscreen-post-process-pass.ts +41 -9
  519. package/src/gpu-dirty-ranges.ts +48 -0
  520. package/src/gpu-driven/batch-topology.ts +53 -0
  521. package/src/gpu-driven/material-artifacts.ts +35 -32
  522. package/src/gpu-driven/prepared-draw.ts +27 -14
  523. package/src/gpu-driven/production-raster-material.ts +1894 -0
  524. package/src/gpu-driven/production-raster.ts +904 -787
  525. package/src/gpu-driven/resource-allocation.ts +142 -0
  526. package/src/gpu-driven/shadow-ownership.ts +71 -0
  527. package/src/gpu-driven/view-gpu.ts +181 -10
  528. package/src/gpu-scene.ts +259 -101
  529. package/src/hdrp-buffers.ts +4 -3
  530. package/src/ibl/skylight-bind-group.ts +49 -7
  531. package/src/index.ts +228 -9
  532. package/src/inspection-types.ts +222 -2
  533. package/src/instance-buffer-cache.ts +4 -4
  534. package/src/instances.ts +151 -492
  535. package/src/pbr-pipeline.ts +219 -13
  536. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  537. package/src/pipeline/standard-forward-lane.ts +313 -57
  538. package/src/pipeline/standard-output/graph.ts +8 -2
  539. package/src/pipeline/standard-output/types.ts +12 -1
  540. package/src/pipeline/standard-pipeline.ts +291 -18
  541. package/src/pipeline/standard-post.ts +397 -102
  542. package/src/pipeline-builder.ts +1 -1
  543. package/src/pipeline-spec.ts +5 -5
  544. package/src/plugin.ts +4 -0
  545. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  546. package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
  547. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  548. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  549. package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
  550. package/src/record/__tests__/temporal-payload.unit.test.ts +3 -2
  551. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  552. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  553. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  554. package/src/record/barrel-distortion-frame.ts +110 -0
  555. package/src/record/dynamic-geometry-consumption.ts +39 -9
  556. package/src/record/fold-buckets.ts +852 -0
  557. package/src/record/fold-instance-buffer.ts +51 -0
  558. package/src/record/frame-lighting.ts +36 -2
  559. package/src/record/frame-snapshot.ts +44 -4
  560. package/src/record/frame-targets.ts +10 -6
  561. package/src/record/frame.ts +373 -1099
  562. package/src/record/gpu-draw-receipts.ts +38 -0
  563. package/src/record/gpu-timing.ts +48 -5
  564. package/src/record/main-pass-geometry.ts +281 -83
  565. package/src/record/main-pass-material.ts +66 -4
  566. package/src/record/main-pass-sprite-draws.ts +13 -66
  567. package/src/record/main-pass.ts +156 -20
  568. package/src/record/mesh-ssbo.ts +43 -6
  569. package/src/record/motion-blur-receipt.ts +91 -0
  570. package/src/record/probe-blend-buffer.ts +180 -0
  571. package/src/record/recovery-pipeline.ts +35 -3
  572. package/src/record/render-context.ts +51 -31
  573. package/src/record/shadow-pass.ts +36 -2
  574. package/src/record/skybox-post-pass.ts +150 -200
  575. package/src/record/typed-frame-graph.ts +824 -44
  576. package/src/record/view-ubo.ts +26 -3
  577. package/src/record/volume-params.ts +225 -0
  578. package/src/recovery/render-system-candidate.ts +257 -52
  579. package/src/reflection/record-owner.ts +7 -3
  580. package/src/render-contract.ts +71 -8
  581. package/src/render-graph-primitives.ts +7 -1
  582. package/src/render-pipeline.ts +136 -1
  583. package/src/render-system-extract-tail.ts +72 -60
  584. package/src/render-system-extract.ts +117 -87
  585. package/src/render-system-presentation.ts +56 -0
  586. package/src/render-system-producer-roots.ts +96 -0
  587. package/src/render-system-residency.ts +159 -0
  588. package/src/render-system.ts +601 -482
  589. package/src/scene/probe-blend.ts +96 -4
  590. package/src/scene/render-scene.ts +431 -281
  591. package/src/ssao-buffers.ts +95 -2
  592. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  593. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  594. package/src/surface/dynamic-input.ts +658 -0
  595. package/src/surface/gpu-driven.ts +147 -0
  596. package/src/surface/submission-observation.ts +517 -0
  597. package/src/systems/skin-palette-allocator.ts +4 -1
  598. package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
  599. package/src/temporal/frame-coordinator.ts +8 -1
  600. package/src/temporal/frame.ts +20 -0
  601. package/src/temporal/gpu.ts +101 -17
  602. package/src/temporal/inspection.ts +7 -1
  603. package/src/temporal/standard-scene-data.ts +5 -0
  604. package/src/temporal/target-coverage-attachment.ts +4 -0
  605. package/src/temporal/view.ts +13 -2
  606. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  607. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  608. package/src/transmission/single-layer-medium.ts +322 -0
  609. package/src/typed-render-graph-primitives.ts +191 -50
  610. package/src/volume/component.ts +10 -10
  611. package/src/volume/extract.ts +11 -5
  612. package/src/volume/inspection.ts +3 -0
  613. package/src/volume/passes.ts +95 -8
  614. package/src/volume/resources.ts +2 -1
  615. package/src/volume/temporal.ts +11 -0
  616. package/dist/chunk-4NNZQCL3.mjs.map +0 -1
  617. package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
  618. package/dist/chunk-DRR7D3KX.mjs.map +0 -1
  619. package/dist/chunk-GWCEMDVR.mjs.map +0 -1
  620. package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
  621. package/dist/chunk-JRIPCMYC.mjs.map +0 -1
  622. package/dist/chunk-LULCA3OF.mjs +0 -1713
  623. package/dist/chunk-LULCA3OF.mjs.map +0 -1
  624. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
package/src/gpu-scene.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { Buffer, Result, RhiDevice } from '@forgeax/engine-rhi';
2
2
  import { err, ok, RhiError } from '@forgeax/engine-rhi';
3
3
  import { createStandardPbrArtifactReceipt } from '@forgeax/engine-shader';
4
+ import { GpuDirtyRanges } from './gpu-dirty-ranges';
4
5
  import {
5
6
  GPU_SCENE_LAYOUTS,
6
7
  type GpuSceneTableLayout,
@@ -13,10 +14,14 @@ import {
13
14
  } from './gpu-usage';
14
15
  import type { GpuSceneInspection } from './inspection-types';
15
16
  import { packMaterialProgramRow, packStandardPbrMaterialRow } from './material-row';
17
+ import type { MaterialSnapshot } from './render-system-extract';
16
18
  import type { RenderSceneApplyResult, RenderSceneSlot } from './scene/render-scene-types';
17
19
 
18
20
  export type { GpuSceneInspection } from './inspection-types';
19
21
 
22
+ type GpuSceneTemporalSnapshot = NonNullable<RenderSceneSlot['snapshot']['temporal']>;
23
+ type GpuSceneTemporalResolver = (slot: RenderSceneSlot) => GpuSceneTemporalSnapshot | undefined;
24
+
20
25
  const PRIMITIVE = GPU_SCENE_LAYOUTS.primitive;
21
26
  const INSTANCE = GPU_SCENE_LAYOUTS.instance;
22
27
  const TRANSFORM = GPU_SCENE_LAYOUTS.transform;
@@ -203,24 +208,61 @@ function stableU32(value: string): number {
203
208
  return hash >>> 0;
204
209
  }
205
210
 
206
- function coalesceSlots(
207
- slots: readonly number[],
208
- ): readonly { readonly start: number; readonly end: number }[] {
209
- const ordered = [...new Set(slots)].sort((a, b) => a - b);
210
- const ranges: Array<{ start: number; end: number }> = [];
211
- for (const slot of ordered) {
212
- const previous = ranges.at(-1);
213
- if (previous !== undefined && previous.end === slot) {
214
- previous.end = slot + 1;
215
- } else {
216
- ranges.push({ start: slot, end: slot + 1 });
217
- }
211
+ /**
212
+ * Build a lookup from the current instance identity to its submitted ordinal.
213
+ * The GPU table is physically compacted by ordinal, so this small CPU lookup
214
+ * is the seam that keeps a stable logical instance from inheriting another
215
+ * row's previous transform after reorder. A missing or duplicate generation
216
+ * deliberately returns no proof and makes the caller seed the current pose.
217
+ */
218
+ function previousInstanceOrdinals(
219
+ current: NonNullable<RenderSceneSlot['snapshot']['instances']> | undefined,
220
+ temporal: GpuSceneTemporalSnapshot | undefined,
221
+ ): Map<number, number> | undefined {
222
+ const previous = temporal?.previousInstances;
223
+ const currentGenerations = current?.generations;
224
+ const previousGenerations = previous?.generations;
225
+ if (
226
+ temporal?.motionValid !== true ||
227
+ current === undefined ||
228
+ previous === undefined ||
229
+ currentGenerations === undefined ||
230
+ previousGenerations === undefined ||
231
+ currentGenerations.length !== current.instanceCount ||
232
+ previousGenerations.length !== previous.instanceCount ||
233
+ current.transforms.length < current.instanceCount * 16 ||
234
+ previous.transforms.length < previous.instanceCount * 16
235
+ ) {
236
+ return undefined;
218
237
  }
219
- return ranges;
238
+ const currentSet = new Set<number>();
239
+ for (const generation of currentGenerations) {
240
+ if (generation === 0 || currentSet.has(generation)) return undefined;
241
+ currentSet.add(generation);
242
+ }
243
+ const ordinals = new Map<number, number>();
244
+ for (let ordinal = 0; ordinal < previousGenerations.length; ordinal += 1) {
245
+ const generation = previousGenerations[ordinal] ?? 0;
246
+ if (generation === 0 || ordinals.has(generation)) return undefined;
247
+ ordinals.set(generation, ordinal);
248
+ }
249
+ return ordinals;
250
+ }
251
+
252
+ function instanceIdentityChanged(
253
+ resident: Uint32Array | undefined,
254
+ current: Uint32Array | undefined,
255
+ ordinal: number,
256
+ ): boolean {
257
+ if (resident === undefined || current === undefined) return resident !== current;
258
+ return resident[ordinal] !== current[ordinal];
220
259
  }
221
260
 
222
261
  /** Persistent GPU tables derived only from renderer projection slots. */
223
262
  export class GpuScene {
263
+ private readonly dirtyRanges = new GpuDirtyRanges();
264
+ private readonly rowScratch = new Uint8Array(Math.max(PRIMITIVE.stride, DRAW_TEMPLATE.stride));
265
+ private readonly rowScratchView = new DataView(this.rowScratch.buffer);
224
266
  private disposed = false;
225
267
  private tableBytes: Record<GpuSceneTableName, ArrayBuffer>;
226
268
  private transformBytes: Uint8Array;
@@ -238,6 +280,8 @@ export class GpuScene {
238
280
  private sceneContentRevision = 0;
239
281
  private identityUploaded = false;
240
282
  private readonly allocations = new Map<number, PrimitiveAllocation>();
283
+ /** Current stable instance identities retained beside compact GPU rows. */
284
+ private readonly instanceGenerations = new Map<number, Uint32Array>();
241
285
  private readonly instances = new StableRangeAllocator();
242
286
  private readonly transforms = new StableRangeAllocator();
243
287
  private readonly draws = new StableRangeAllocator();
@@ -322,7 +366,10 @@ export class GpuScene {
322
366
  return allocation.materialStart + materialSlot;
323
367
  }
324
368
 
325
- sync(delta: RenderSceneApplyResult): Result<GpuSceneSyncResult, RhiError> {
369
+ sync(
370
+ delta: RenderSceneApplyResult,
371
+ temporalResolver?: GpuSceneTemporalResolver,
372
+ ): Result<GpuSceneSyncResult, RhiError> {
326
373
  for (const transformIndex of this.pendingTemporalUploads) {
327
374
  this.writesByTable.transform.push(transformIndex);
328
375
  }
@@ -386,6 +433,9 @@ export class GpuScene {
386
433
  if (!grown.ok) return grown;
387
434
  }
388
435
 
436
+ // A shared material has one packed value per publication, independent of
437
+ // how many primitives reference it. Do not retain mutable caller snapshots.
438
+ const materialRows = new Map<MaterialSnapshot, Uint8Array>();
389
439
  const publications = [...delta.createdSlots, ...delta.updatedSlots, ...delta.recreatedSlots];
390
440
  const newSlots = new Set(
391
441
  [...delta.createdSlots, ...delta.recreatedSlots].map((record) => record.slot),
@@ -393,11 +443,11 @@ export class GpuScene {
393
443
  for (const record of publications) {
394
444
  const reset = newSlots.has(record.slot) || allocationResets.has(record.slot);
395
445
  if (reset || contentUpdatedSlotIds.has(record.slot)) {
396
- this.writeSlot(record, reset, writesByTable);
446
+ this.writeSlot(record, reset, writesByTable, materialRows, temporalResolver?.(record));
397
447
  continue;
398
448
  }
399
449
  if (instanceUpdatedSlotIds.has(record.slot))
400
- this.writeInstanceTransforms(record, writesByTable);
450
+ this.writeInstanceTransforms(record, writesByTable, temporalResolver?.(record));
401
451
  this.writeRootTransform(record, false, writesByTable);
402
452
  }
403
453
  const uploaded = this.uploadRows(writesByTable);
@@ -425,7 +475,7 @@ export class GpuScene {
425
475
  if (this.pendingTemporalTransforms.size === 0) return ok(undefined);
426
476
  const currentOffset = offset(TRANSFORM, 'currentWorld');
427
477
  const previousOffset = offset(TRANSFORM, 'previousWorld');
428
- const ranges = coalesceSlots([...this.pendingTemporalTransforms]);
478
+ const ranges = this.dirtyRanges.coalesce([...this.pendingTemporalTransforms]);
429
479
  for (const range of ranges) {
430
480
  for (let index = range.start; index < range.end; index += 1) {
431
481
  this.pendingTemporalUploads.add(index);
@@ -459,6 +509,7 @@ export class GpuScene {
459
509
 
460
510
  rebuild(slots: readonly RenderSceneSlot[]): Result<GpuSceneSyncResult, RhiError> {
461
511
  this.allocations.clear();
512
+ this.instanceGenerations.clear();
462
513
  this.instances.reset();
463
514
  this.transforms.reset(1);
464
515
  this.draws.reset();
@@ -490,7 +541,8 @@ export class GpuScene {
490
541
  }
491
542
  for (const bytes of Object.values(this.tableBytes)) new Uint8Array(bytes).fill(0);
492
543
  this.writeIdentityTransform();
493
- for (const slot of slots) this.writeSlot(slot, true, writesByTable);
544
+ const materialRows = new Map<MaterialSnapshot, Uint8Array>();
545
+ for (const slot of slots) this.writeSlot(slot, true, writesByTable, materialRows);
494
546
  let bytes = 0;
495
547
  for (const name of TABLE_NAMES) {
496
548
  const table = this.tableBytes[name];
@@ -551,65 +603,51 @@ export class GpuScene {
551
603
  record: RenderSceneSlot,
552
604
  resetPrevious: boolean,
553
605
  writes: Record<GpuSceneTableName, number[]>,
606
+ materialRows: Map<MaterialSnapshot, Uint8Array>,
607
+ temporal?: GpuSceneTemporalSnapshot,
554
608
  ): void {
555
609
  const allocation = this.allocations.get(record.slot);
556
610
  if (allocation === undefined) throw new RangeError('GPU Scene allocation unavailable');
557
- const primitiveOffset = record.slot * PRIMITIVE.stride;
558
- const primitive = new DataView(this.tableBytes.primitive);
611
+ this.rowScratch.fill(0);
612
+ const primitive = this.rowScratchView;
559
613
  const bounds = record.snapshot.localAabb;
560
- primitive.setUint32(primitiveOffset + offset(PRIMITIVE, 'generation'), record.generation, true);
614
+ primitive.setUint32(offset(PRIMITIVE, 'generation'), record.generation, true);
561
615
  primitive.setUint32(
562
- primitiveOffset + offset(PRIMITIVE, 'flags'),
616
+ offset(PRIMITIVE, 'flags'),
563
617
  PRIMITIVE_ACTIVE |
564
618
  (bounds === undefined ? 0 : PRIMITIVE_HAS_BOUNDS) |
565
619
  (record.snapshot.gpuDrivenDraws === undefined ? 0 : PRIMITIVE_GPU_DRIVEN),
566
620
  true,
567
621
  );
568
- primitive.setUint32(
569
- primitiveOffset + offset(PRIMITIVE, 'transformIndex'),
570
- allocation.transformStart,
571
- true,
572
- );
573
- primitive.setUint32(
574
- primitiveOffset + offset(PRIMITIVE, 'materialIndex'),
575
- allocation.materialStart,
576
- true,
577
- );
578
- primitive.setUint32(
579
- primitiveOffset + offset(PRIMITIVE, 'drawTemplateIndex'),
580
- allocation.drawStart,
581
- true,
582
- );
583
- primitive.setUint32(
584
- primitiveOffset + offset(PRIMITIVE, 'instanceStart'),
585
- allocation.instanceStart,
586
- true,
587
- );
588
- primitive.setUint32(
589
- primitiveOffset + offset(PRIMITIVE, 'instanceCount'),
590
- allocation.instanceCount,
591
- true,
592
- );
593
- primitive.setUint32(
594
- primitiveOffset + offset(PRIMITIVE, 'assetHandle'),
595
- record.snapshot.assetHandle,
596
- true,
597
- );
598
- writeVec4(primitive, primitiveOffset + offset(PRIMITIVE, 'localBoundsMin'), [
622
+ primitive.setUint32(offset(PRIMITIVE, 'transformIndex'), allocation.transformStart, true);
623
+ primitive.setUint32(offset(PRIMITIVE, 'materialIndex'), allocation.materialStart, true);
624
+ primitive.setUint32(offset(PRIMITIVE, 'drawTemplateIndex'), allocation.drawStart, true);
625
+ primitive.setUint32(offset(PRIMITIVE, 'instanceStart'), allocation.instanceStart, true);
626
+ primitive.setUint32(offset(PRIMITIVE, 'instanceCount'), allocation.instanceCount, true);
627
+ primitive.setUint32(offset(PRIMITIVE, 'assetHandle'), record.snapshot.assetHandle, true);
628
+ writeVec4(primitive, offset(PRIMITIVE, 'localBoundsMin'), [
599
629
  bounds?.[0] ?? 0,
600
630
  bounds?.[1] ?? 0,
601
631
  bounds?.[2] ?? 0,
602
632
  0,
603
633
  ]);
604
- writeVec4(primitive, primitiveOffset + offset(PRIMITIVE, 'localBoundsMax'), [
634
+ writeVec4(primitive, offset(PRIMITIVE, 'localBoundsMax'), [
605
635
  bounds?.[3] ?? 0,
606
636
  bounds?.[4] ?? 0,
607
637
  bounds?.[5] ?? 0,
608
638
  0,
609
639
  ]);
610
640
 
641
+ if (this.writeRow('primitive', record.slot, this.rowScratch) || resetPrevious)
642
+ writes.primitive.push(record.slot);
643
+
611
644
  const instance = new DataView(this.tableBytes.instance);
612
645
  const transform = this.transformView;
646
+ const instances = record.snapshot.instances;
647
+ const previousInstances = temporal?.previousInstances;
648
+ const previousOrdinals = previousInstanceOrdinals(instances, temporal);
649
+ const currentGenerations = instances?.generations;
650
+ const residentGenerations = this.instanceGenerations.get(record.slot);
613
651
  for (let ordinal = 0; ordinal < allocation.instanceCount; ordinal += 1) {
614
652
  const instanceIndex = allocation.instanceStart + ordinal;
615
653
  const instanceOffset = instanceIndex * INSTANCE.stride;
@@ -636,7 +674,7 @@ export class GpuScene {
636
674
  writeChangedU32(instance, instanceOffset + offset(INSTANCE, 'flags'), PRIMITIVE_ACTIVE) ||
637
675
  metadataChanged;
638
676
  if (allocation.instanceTransformCount > 0) {
639
- const transforms = record.snapshot.instances?.transforms;
677
+ const transforms = instances?.transforms;
640
678
  const hasLocal = transforms !== undefined && transforms.length >= (ordinal + 1) * 16;
641
679
  const local = hasLocal ? transforms : IDENTITY_MATRIX;
642
680
  const sourceOffset = hasLocal ? ordinal * 16 : 0;
@@ -647,30 +685,76 @@ export class GpuScene {
647
685
  local,
648
686
  sourceOffset,
649
687
  );
650
- if (resetPrevious)
651
- writeChangedMat4(
652
- transform,
653
- localOffset + offset(TRANSFORM, 'previousWorld'),
654
- local,
655
- sourceOffset,
656
- );
657
- else if (changed) this.pendingTemporalTransforms.add(transformIndex);
658
- if (changed || resetPrevious) writes.transform.push(transformIndex);
688
+ const identityChanged = instanceIdentityChanged(
689
+ residentGenerations,
690
+ currentGenerations,
691
+ ordinal,
692
+ );
693
+ if (resetPrevious) {
694
+ const previousOrdinal = previousOrdinals?.get(currentGenerations?.[ordinal] ?? 0);
695
+ const previousSource =
696
+ previousOrdinal === undefined || previousInstances === undefined
697
+ ? undefined
698
+ : previousInstances.transforms;
699
+ if (previousSource === undefined || previousOrdinal === undefined) {
700
+ writeChangedMat4(
701
+ transform,
702
+ localOffset + offset(TRANSFORM, 'previousWorld'),
703
+ local,
704
+ sourceOffset,
705
+ );
706
+ } else {
707
+ writeChangedMat4(
708
+ transform,
709
+ localOffset + offset(TRANSFORM, 'previousWorld'),
710
+ previousSource,
711
+ previousOrdinal * 16,
712
+ );
713
+ this.pendingTemporalTransforms.add(transformIndex);
714
+ }
715
+ } else if (changed || identityChanged) {
716
+ const previousOrdinal = previousOrdinals?.get(currentGenerations?.[ordinal] ?? 0);
717
+ const previousSource =
718
+ previousOrdinal === undefined || previousInstances === undefined
719
+ ? undefined
720
+ : previousInstances.transforms;
721
+ if (previousSource === undefined || previousOrdinal === undefined) {
722
+ // A changed row without an identity proof must not borrow the
723
+ // compacted row's old velocity. Seed only this row and keep other
724
+ // stable instances eligible for motion.
725
+ writeChangedMat4(
726
+ transform,
727
+ localOffset + offset(TRANSFORM, 'previousWorld'),
728
+ local,
729
+ sourceOffset,
730
+ );
731
+ } else {
732
+ writeChangedMat4(
733
+ transform,
734
+ localOffset + offset(TRANSFORM, 'previousWorld'),
735
+ previousSource,
736
+ previousOrdinal * 16,
737
+ );
738
+ }
739
+ this.pendingTemporalTransforms.add(transformIndex);
740
+ }
741
+ if (changed || identityChanged || resetPrevious) writes.transform.push(transformIndex);
659
742
  }
660
743
  if (metadataChanged || resetPrevious) writes.instance.push(instanceIndex);
661
744
  }
662
745
 
746
+ this.rememberInstanceGenerations(record.slot, currentGenerations, allocation.instanceCount);
747
+
663
748
  this.writeRootTransform(record, resetPrevious, writes);
664
- writes.primitive.push(record.slot);
665
749
 
666
- const draw = new DataView(this.tableBytes.drawTemplate);
750
+ const draw = this.rowScratchView;
667
751
  const drawSnapshots = record.snapshot.gpuDrivenDraws ?? [];
668
752
  for (let ordinal = 0; ordinal < allocation.drawCount; ordinal += 1) {
669
753
  const drawIndex = allocation.drawStart + ordinal;
670
- const drawOffset = drawIndex * DRAW_TEMPLATE.stride;
754
+ this.rowScratch.fill(0);
671
755
  const drawSnapshot = drawSnapshots[ordinal];
672
756
  draw.setUint32(
673
- drawOffset + offset(DRAW_TEMPLATE, 'pipelineClass'),
757
+ offset(DRAW_TEMPLATE, 'pipelineClass'),
674
758
  drawSnapshot === undefined
675
759
  ? 0
676
760
  : stableU32(
@@ -681,58 +765,77 @@ export class GpuScene {
681
765
  true,
682
766
  );
683
767
  draw.setUint32(
684
- drawOffset + offset(DRAW_TEMPLATE, 'materialIndex'),
768
+ offset(DRAW_TEMPLATE, 'materialIndex'),
685
769
  allocation.materialStart + (drawSnapshot?.materialSlot ?? 0),
686
770
  true,
687
771
  );
688
772
  draw.setUint32(
689
- drawOffset + offset(DRAW_TEMPLATE, 'firstIndex'),
773
+ offset(DRAW_TEMPLATE, 'firstIndex'),
690
774
  drawSnapshot?.prepared?.first ?? drawSnapshot?.first ?? 0,
691
775
  true,
692
776
  );
693
777
  draw.setUint32(
694
- drawOffset + offset(DRAW_TEMPLATE, 'indexCount'),
778
+ offset(DRAW_TEMPLATE, 'indexCount'),
695
779
  drawSnapshot?.prepared?.count ?? drawSnapshot?.count ?? 0,
696
780
  true,
697
781
  );
698
782
  draw.setInt32(
699
- drawOffset + offset(DRAW_TEMPLATE, 'baseVertex'),
783
+ offset(DRAW_TEMPLATE, 'baseVertex'),
700
784
  drawSnapshot?.prepared?.baseVertex ?? drawSnapshot?.baseVertex ?? 0,
701
785
  true,
702
786
  );
703
- draw.setUint32(drawOffset + offset(DRAW_TEMPLATE, 'firstInstance'), 0, true);
704
- draw.setUint32(drawOffset + offset(DRAW_TEMPLATE, 'passFlags'), 0, true);
705
- draw.setUint32(drawOffset + offset(DRAW_TEMPLATE, 'reserved'), 0, true);
706
- writes.drawTemplate.push(drawIndex);
787
+ draw.setUint32(offset(DRAW_TEMPLATE, 'firstInstance'), 0, true);
788
+ draw.setUint32(offset(DRAW_TEMPLATE, 'passFlags'), 0, true);
789
+ draw.setUint32(offset(DRAW_TEMPLATE, 'reserved'), 0, true);
790
+ if (this.writeRow('drawTemplate', drawIndex, this.rowScratch) || resetPrevious)
791
+ writes.drawTemplate.push(drawIndex);
707
792
  }
708
793
 
709
- this.writeMaterialSlot(record, writes);
794
+ this.writeMaterialSlot(record, writes, materialRows, resetPrevious);
795
+ }
796
+
797
+ /** Compare against the resident CPU bytes; pending upload rows survive failure. */
798
+ private writeRow(table: GpuSceneTableName, index: number, row: Uint8Array): boolean {
799
+ const stride = TABLE_LAYOUTS[table].stride;
800
+ const destination = new Uint8Array(this.tableBytes[table], index * stride, stride);
801
+ let changed = false;
802
+ for (let byte = 0; byte < stride; byte += 1) {
803
+ const value = row[byte] ?? 0;
804
+ if (destination[byte] === value) continue;
805
+ destination[byte] = value;
806
+ changed = true;
807
+ }
808
+ return changed;
710
809
  }
711
810
 
712
811
  private writeMaterialSlot(
713
812
  record: RenderSceneSlot,
714
813
  writes: Record<GpuSceneTableName, number[]>,
814
+ materialRows: Map<MaterialSnapshot, Uint8Array>,
815
+ reset: boolean,
715
816
  ): void {
716
817
  const allocation = this.allocations.get(record.slot);
717
818
  if (allocation === undefined) throw new RangeError('GPU Scene allocation unavailable');
718
819
  for (let ordinal = 0; ordinal < allocation.materialCount; ordinal += 1) {
719
820
  const materialIndex = allocation.materialStart + ordinal;
720
- const materialOffset = materialIndex * MATERIAL.stride;
721
821
  const snapshot = record.snapshot.materials[ordinal] ?? record.snapshot.material;
722
- const shaderId = snapshot.materialShaderId;
723
- const schema = snapshot.materialParamSchema;
724
- const row =
725
- shaderId !== undefined &&
726
- shaderId !== 'forgeax::default-standard-pbr' &&
727
- shaderId !== 'forgeax::pbr-skin' &&
728
- shaderId !== 'forgeax::default-standard-pbr-skin' &&
729
- schema !== undefined
730
- ? packMaterialProgramRow(schema, snapshot, MATERIAL.stride)
731
- : packStandardPbrMaterialRow(STANDARD_PBR_RECEIPT, snapshot);
732
- const destination = new Uint8Array(this.tableBytes.material, materialOffset, MATERIAL.stride);
733
- destination.fill(0);
734
- if (row !== undefined) destination.set(row.subarray(0, MATERIAL.stride));
735
- writes.material.push(materialIndex);
822
+ let row = materialRows.get(snapshot);
823
+ if (row === undefined) {
824
+ const shaderId = snapshot.materialShaderId;
825
+ const schema = snapshot.materialParamSchema;
826
+ row =
827
+ shaderId !== undefined &&
828
+ shaderId !== 'forgeax::default-standard-pbr' &&
829
+ shaderId !== 'forgeax::pbr-skin' &&
830
+ shaderId !== 'forgeax::default-standard-pbr-skin' &&
831
+ schema !== undefined
832
+ ? packMaterialProgramRow(schema, snapshot, MATERIAL.stride)
833
+ : packStandardPbrMaterialRow(STANDARD_PBR_RECEIPT, snapshot);
834
+ row ??= new Uint8Array(MATERIAL.stride);
835
+ materialRows.set(snapshot, row);
836
+ }
837
+ if (this.writeRow('material', materialIndex, row) || reset)
838
+ writes.material.push(materialIndex);
736
839
  }
737
840
  }
738
841
 
@@ -740,6 +843,7 @@ export class GpuScene {
740
843
  private writeInstanceTransforms(
741
844
  record: RenderSceneSlot,
742
845
  writes: Record<GpuSceneTableName, number[]>,
846
+ temporal?: GpuSceneTemporalSnapshot,
743
847
  ): void {
744
848
  const allocation = this.allocations.get(record.slot);
745
849
  const instances = record.snapshot.instances;
@@ -749,21 +853,74 @@ export class GpuScene {
749
853
  if (allocation.instanceTransformCount !== instances.instanceCount) {
750
854
  throw new RangeError('GPU Scene instance update changed instance count');
751
855
  }
856
+ const previousOrdinals = previousInstanceOrdinals(instances, temporal);
857
+ const previousInstances = temporal?.previousInstances;
858
+ const currentGenerations = instances.generations;
859
+ const residentGenerations = this.instanceGenerations.get(record.slot);
752
860
  for (let ordinal = 0; ordinal < allocation.instanceTransformCount; ordinal += 1) {
753
861
  const transformIndex = allocation.instanceTransformStart + ordinal;
754
862
  const transformOffset = transformIndex * TRANSFORM.stride;
755
- if (
756
- writeChangedMat4(
757
- this.transformView,
758
- transformOffset + offset(TRANSFORM, 'currentWorld'),
759
- instances.transforms,
760
- ordinal * 16,
761
- )
762
- ) {
863
+ const changed = writeChangedMat4(
864
+ this.transformView,
865
+ transformOffset + offset(TRANSFORM, 'currentWorld'),
866
+ instances.transforms,
867
+ ordinal * 16,
868
+ );
869
+ const identityChanged = instanceIdentityChanged(
870
+ residentGenerations,
871
+ currentGenerations,
872
+ ordinal,
873
+ );
874
+ if (changed || identityChanged) {
875
+ const previousOrdinal = previousOrdinals?.get(currentGenerations?.[ordinal] ?? 0);
876
+ const previousSource =
877
+ previousOrdinal === undefined || previousInstances === undefined
878
+ ? undefined
879
+ : previousInstances.transforms;
880
+ if (previousSource === undefined || previousOrdinal === undefined) {
881
+ writeChangedMat4(
882
+ this.transformView,
883
+ transformOffset + offset(TRANSFORM, 'previousWorld'),
884
+ instances.transforms,
885
+ ordinal * 16,
886
+ );
887
+ } else {
888
+ writeChangedMat4(
889
+ this.transformView,
890
+ transformOffset + offset(TRANSFORM, 'previousWorld'),
891
+ previousSource,
892
+ previousOrdinal * 16,
893
+ );
894
+ }
763
895
  this.pendingTemporalTransforms.add(transformIndex);
764
896
  writes.transform.push(transformIndex);
765
897
  }
766
898
  }
899
+ this.rememberInstanceGenerations(
900
+ record.slot,
901
+ currentGenerations,
902
+ allocation.instanceTransformCount,
903
+ );
904
+ }
905
+
906
+ private rememberInstanceGenerations(
907
+ slot: number,
908
+ generations: Uint32Array | undefined,
909
+ instanceCount: number,
910
+ ): void {
911
+ if (generations === undefined || generations.length !== instanceCount) {
912
+ this.instanceGenerations.delete(slot);
913
+ return;
914
+ }
915
+ const resident = this.instanceGenerations.get(slot);
916
+ if (
917
+ resident !== undefined &&
918
+ resident.length === generations.length &&
919
+ resident.every((generation, ordinal) => generation === generations[ordinal])
920
+ ) {
921
+ return;
922
+ }
923
+ this.instanceGenerations.set(slot, generations.slice());
767
924
  }
768
925
 
769
926
  private writeRootTransform(
@@ -795,6 +952,7 @@ export class GpuScene {
795
952
  }
796
953
  const allocation = this.allocations.get(slot);
797
954
  if (allocation === undefined) return;
955
+ this.instanceGenerations.delete(slot);
798
956
  this.clearAllocation(allocation, writes);
799
957
  this.allocations.delete(slot);
800
958
  }
@@ -805,7 +963,7 @@ export class GpuScene {
805
963
  let rangeCount = 0;
806
964
  let bytes = 0;
807
965
  for (const name of TABLE_NAMES) {
808
- const ranges = coalesceSlots(rows[name]);
966
+ const ranges = this.dirtyRanges.coalesce(rows[name]);
809
967
  rangeCount += ranges.length;
810
968
  for (const range of ranges) {
811
969
  const layout = TABLE_LAYOUTS[name];
@@ -559,6 +559,7 @@ export function createHdrpUnifiedBindGroup(
559
559
  hdrpBuffers: HdrpBuffers,
560
560
  meshStorageBuffer: Buffer,
561
561
  ssaoOptions: SsaoBindOptions = { enabled: false },
562
+ meshBindingBytes = MESH_PER_ENTITY_STRIDE,
562
563
  ): BindGroup | null {
563
564
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
564
565
  if (fallback === null) return null;
@@ -579,7 +580,7 @@ export function createHdrpUnifiedBindGroup(
579
580
  value: {
580
581
  buffer: meshStorageBuffer,
581
582
  offset: 0,
582
- size: MESH_PER_ENTITY_STRIDE,
583
+ size: meshBindingBytes,
583
584
  },
584
585
  },
585
586
  },
@@ -602,17 +603,17 @@ export function createHdrpSkinUnifiedBindGroup(
602
603
  paletteBuffer: Buffer,
603
604
  paletteBindingWindowBytes: number,
604
605
  ssaoOptions: SsaoBindOptions = { enabled: false },
606
+ meshBindingBytes = MESH_PER_ENTITY_STRIDE,
605
607
  ): BindGroup | null {
606
608
  const fallback = getOrCreateSsaoFallbackTexture(runtime);
607
609
  if (fallback === null) return null;
608
- const meshSize = MESH_PER_ENTITY_STRIDE;
609
610
  const result = runtime.device.createBindGroup({
610
611
  label: 'hdrp-skin-unified-bg-group2',
611
612
  layout,
612
613
  entries: [
613
614
  ...createPbrSkinMeshBindGroupEntries(
614
615
  meshStorageBuffer,
615
- meshSize,
616
+ meshBindingBytes,
616
617
  paletteBuffer,
617
618
  paletteBindingWindowBytes,
618
619
  ),